c# - 最快的多线程解析串口数据的方法C#

标签 c# parsing serial-port

我目前正在编写一个通过串行连接与集成伺服系统通信的应用程序。

电机以高达 1000 次/秒的速率发出位置数据。我想要实现的是能够格式化返回的数据(通过去除空格、换行等)并解析它以从接收到的字符串中提取相关数据。

目前,我让数据接收事件处理程序读取数据,使用一系列 string.replace 方法调用对其进行格式化,并将其附加到充当缓冲区的字符串。然后,使用线程,我不断地检查缓冲区,因为它填充了一个特定的分隔符(在我的例子中是“\r”),它表示来自电机的一条消息的结尾,然后从缓冲区中删除该消息并将其打印到一个 rich文本字段。

这种方法有两个问题。一是因为电机以如此高的速率传输位置数据,缓冲区填充速度快于线程处理数据的速度。因此,当我向电机发送命令时,它会立即 Action ,但响应会延迟几秒钟,因为必须首先处理缓冲区中的所有先前数据。其次,让两个线程运行一个实现 while(true) 结构的方法意味着处理器利用率飙升,并且在几秒钟内 pc 中的风扇就达到最大。

是否有更好的数据处理方式?

这是我的事件处理程序代码:

 //data recieved event handler
    private void dataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        string tmp;

            tmp = sp.ReadExisting();

            //cut out any unnecessary characters
            tmp = tmp.Replace("\n", "");
            tmp = tmp.Replace(",", "\r");
            tmp = tmp.Replace(" ", "");

            lock (this)
            {
                //put all received data into the read buffer
                readBuffer += tmp;
           }

    }

线程执行的方法如下:

 private void parseBuffer()
    {
        while (true)
        {
            //obtain lock, parse one message from buffer
            lock (this)
            {
                if (readBuffer.IndexOf("\r") > 0)
                {
                    String t = readBuffer.Substring(0, readBuffer.IndexOf("\r") + 1);
                    readBuffer = readBuffer.Replace(t, "");
                    dataReady(this, new CustomEventArgs(t, null));
                }
            }
        }
    }

最佳答案

即使自上次尝试以来没有新数据,您的 parseBuffer 也会疯狂旋转。

您可以通过信号来缓解这种情况。

private AutoResetEvent waitHandle = new AutoResetEvent(false);

触发dataReceived中的信号

//data recieved event handler
private void dataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string tmp;

        tmp = sp.ReadExisting();

        //cut out any unnecessary characters
        tmp = tmp.Replace("\n", "");
        tmp = tmp.Replace(",", "\r");
        tmp = tmp.Replace(" ", "");

        lock (this)
        {
            //put all received data into the read buffer
            readBuffer += tmp;
            waitHandle.Set(); // <-- tell parseBuffer that new data is available
       }

}

等待parseBuffer中的信号

private void parseBuffer()
{
    while (true)
    {
        waitHandle.WaitOne(); // <-- waits until there is more data to parse
        //obtain lock, parse one message from buffer
        lock (this)
        {
            if (readBuffer.IndexOf("\r") > 0)
            {
                String t = readBuffer.Substring(0, readBuffer.IndexOf("\r") + 1);
                readBuffer = readBuffer.Replace(t, "");
                dataReady(this, new CustomEventArgs(t, null));
            }
        }
    }
}

关于c# - 最快的多线程解析串口数据的方法C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5993644/

相关文章:

c# - 如何在 C# 中隐藏 ReplyKeyboardMarkup?

c# - Html 敏捷包 : replacing script tags

c++ - 在不打开端口的情况下确定设备是否连接/断开到 RS232 端口

string - 如何在Arduino上使用分隔符读取字符串值?

java - JAX-WS + SOAP : How to parse HTTP Client Error

c - 用C语言设计主站(PC或ARM板)和从站(微处理器)之间简单而强大的串行协议(protocol)

c# - Roslyn 代码分析从无错误解决方案中返回错误的构建错误

c# - 如何在不输入文本的情况下以编程方式显示自动完成

android - 服务器响应 xml 或 json 对象 android

Javascript正则表达式删除不匹配的结束HTML标签?