C# 异步调用机制设计#

C# 异步调用机制设计#,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,要求是连续地从硬件读取数据并将数据发送到 上层用于进一步加工 目前我使用的是同步机制。即 请求-->等待-->读取-->发送以进行处理 do { int ix = iy; iy = 0; if(ix<1) { while (((ix = ReadSst(ref sBuffer)) < 1) && bProcessNotEnded == t

要求是连续地从硬件读取数据并将数据发送到 上层用于进一步加工

目前我使用的是同步机制。即 请求-->等待-->读取-->发送以进行处理

    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); 
do
{
int ix=iy;
iy=0;
如果(ix超时_2000)
{
eErr=CError.TIMEOUT\u ERR;
objLogger.WriteLine(“硬件超时”);
打破
}
}
}
iBytesRead=ix;
如果(iBytes读取0)
iEndPos=sReadMsg.IndexOf('\n',1);
其他的
iEndPos=-1;
如果(sReadMsg.Length>2)
{
如果((iEndPos==0&&sReadMsg[0]='\n')| |(iEndPos>0&&sReadMsg[sReadMsg.Length-1]='\n'&&sReadMsg[sReadMsg.Length-2]='\r')//完成
{
Thread.Sleep(50);//请稍等片刻,以确保没有进一步的输入
如果(sReadMsg.Length>=3&&sReadMsg[sReadMsg.Length-3]==a')
继续;
iy=读数SST(参考sBuffer);
如果(iy==0)
{
bProcessNotEnded=false;
objLogger.WriteLine(“bProcessNotEnded为false,检测到帧结束”);
打破
}
否则如果(iy<0)
{
eErr=CError.BUFF\u KILL;//错误
打破
}
}
}
}while(bProcessnoteded);
ReadSst方法是对硬件的调用,以请求数据

从代码中可以看出,当前逻辑i循环并读取,直到bProcessNotEnded标志为true。一旦在我接收的字符串缓冲区中检测到帧结束,我将标志设置为false,循环停止(从硬件读取也停止)

现在我需要在代码中实现一些并行性来提高性能,我想学习以异步方式进行读取的方式来改进它

任何能帮我改进现有设计的人


提前感谢

通常在.NET中有三种常见的异步工作模式:

  • 文件(.NET 4.0)
  • 对于显然是低级的代码,我会选择1或3,因为2通常用于高级组件

    一般的设计是使用上述任何一种方式在单独的线程中执行循环,循环完成后通知调用线程操作已完成,并以适当的方式(取决于您选择的方式)传递结果(在您的情况下,这应该是
    sReadMsg

    下面是一个简短的示例,说明您可以如何轻松地使用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;
    }
    
    private void ReadMessageAsync()
    {
    //设置任务以从硬件设备读取消息。
    任务readMessageTask=新任务(ReadMessage);
    //设置任务以在从设备读取消息时处理消息。
    readMessageTask.ContinueWith(ProcessMessage);
    //异步启动任务。
    readMessageTask.Start();
    }
    私有void ProcessMessage(任务readMessageTask)
    {
    string message=readMessageTask.Result;
    //处理消息
    }
    私有字符串ReadMessage()
    {
    string message=string.Empty;
    //使用循环检索消息
    返回消息;
    }
    
    有一个名为后台工作者的.net组件,您可以将循环处理放在'DoWork'事件中,同时保持应用程序的响应性

    下面是公开它的类:

    还包含一个如何使用它的好例子


    希望这有帮助

    我认为使用异步IO可以改进您的设计。我们没有看到
    ReadSst
    是如何实现的,但我怀疑您在某处使用了
    流。您不需要调用
    Read
    (同步),而是使用
    BeginRead
    (异步)。此更改将导致代码设计中的其他更重要的更改。我会从研究异步IO开始,自己尝试实现,然后发布后续问题,如果这些问题是我们可以帮助解决的更具体的问题。

    这太低级了。用内存流包装它,您将有同步/异步操作。您好,您可能想在tooHi Florian中发布此消息。我受.NET Framework 2.0的限制,无法使用TPL