Asynchronous calling mechanism design c#
The requirement is to continuosly read the data from a hardware and send the data to the upper layers for further processing.
Presently i use the synchronous mechanism. i.e Request --> Wait --> Read ---> Send for processing.
do
{
int ix = iy;
iy = 0;
if(ix<1)
{
while (((ix = ReadSst(ref sBuffer)) < 1) && bProcessNotEnded == true)
{
if (ix < 0) // BT Error
{
eErr = CError.BUFF_KILL; //Throw error and exit
break;
开发者_如何学编程 }
Thread.Sleep(2);
iTimeOut += 2;
if (iTimeOut > TIMEOUT_2000)
{
eErr = CError.TIMEOUT_ERR;
objLogger.WriteLine("HW TIMED OUT");
break;
}
}
}
iBytesRead = ix;
if (iBytesRead <= 0)
{
eErr = CError.READ_ERR;
objLogger.WriteLine("READ ERROR");
break;
}
sReadMsg = sReadMsg + sBuffer;
if(sReadMsg.Length >0)
iEndPos = sReadMsg.IndexOf('\n',1);
else
iEndPos = -1;
if (sReadMsg.Length > 2)
{
if ((iEndPos == 0 && sReadMsg[0] == '\n') || (iEndPos > 0 && sReadMsg[sReadMsg.Length - 1] == '\n' && sReadMsg[sReadMsg.Length - 2] == '\r')) //finished
{
Thread.Sleep(50); // wait a short time to be sure there that there is no further input
if (sReadMsg.Length >= 3 && sReadMsg[sReadMsg.Length - 3] == 'a')
continue;
iy = ReadSst(ref sBuffer);
if (iy == 0)
{
bProcessNotEnded = false;
objLogger.WriteLine("bProcessNotEnded is made false, End of frame detected");
break;
}
else if (iy < 0)
{
eErr = CError.BUFF_KILL; // error
break;
}
}
}
} while (bProcessNotEnded);
The ReadSst method is a call made to the hardware to request the data.
As seen from the code, the present logic i loop and read till the bProcessNotEnded flag is true. Once the end of frame is detected in the string buffer i receive, i set the flag to false and the looping is stopped (so is the reading from the hardware)
Now that i need to achieve some parallelism in my code to boost performance i want to learn to improve it in a way the reading is done in asynchronous fashion.
Anyone out there who's gonna help me in improving this existing design.
Thanks in advance
Generally there are three common patterns to do asynchronous work in .NET:
- The Asynchronous Programming Model
- The Event-based asynchronous programming model
- The Task parallel library (.NET 4.0)
For your obviously low-level piece of code I would go for 1 or 3, as 2 is usually used on higher level components.
The general design to go for would to execute your loop in a separate thread using any of the above ways and when the loop is finished notifying the calling thread that the operation completed, passing the result (in your case this should be the content of sReadMsg
) in an appropriate way (depends on which way you choose).
Here is a short example on how easily you could do it using TPL:
private void ReadMessageAsync()
{
// Set up the task to read the message from the hardware device.
Task<string> readMessageTask = new Task<string>(ReadMessage);
// Set up the task to process the message when the message was read from the device.
readMessageTask.ContinueWith(ProcessMessage);
// Start the task asynchronously.
readMessageTask.Start();
}
private void ProcessMessage(Task<string> readMessageTask)
{
string message = readMessageTask.Result;
// Process the message
}
private string ReadMessage()
{
string message = string.Empty;
// Retrieve the message using your loop
return message;
}
I think your design could be improved by using asynchronous IO. We did not see how ReadSst
was implemented, but I suspect you are using a Stream
in there somewhere. Instead of calling Read
(which is synchronous) you would use BeginRead
instead (which is asynchronous). This change will lead to other more significant changes in the design of the code. I would start by researching asynchronous IO and attempt an implementation yourself and then post follow up questions if their are more specific issues we can help with.
There is a .net component called Background worker, you can put the loop processing in the 'DoWork' event and keep your application responsive at the same time.
Here is the class that exposes it:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker%28v=VS.90%29.aspx
Also contains a good example of how to use it.
Hope this helps
精彩评论