c# 串口通信 DataReceived 事件触发方法的使用

DataReceived事件:在接收到了ReceivedBytesThreshold设置的字符个数或接收到了文件结束字符并将其放入了输入缓冲区时被触发。数据接收的方法如果采用轮询的方法比较浪费时间,采用DataReceived事件触发的方法,合理的设置ReceivedBytesThreshold的值,若接收的是定长的数据,则将ReceivedBytesThreshold设为接收数据的长度,若接收数据的结尾是是固定的字符或字符串则可采用ReadTo的方法或在DataReceived事件中判断接收的字符是否满足条件。SerialPort读取数据的许多方法都是同步阻塞调用,尽量避免在主线程中调用,可以使用异步处理或线程间处理调用这些读取数据的方法。

Hcom.DataReceived += new SerialDataReceivedEventHandler(H_Decode_com_DataReceived);
Hcom.ReceivedBytesThreshold = 13;

开始时我用while阻塞的方式来保证每次触发DataReceived时把数据取完整:

void H_Decode_com_DataReceived(object sendr, SerialDataReceivedEventArgs e)
{
    byte[] Resoursedata = new byte[6];
    while (Hcom.BytesToRead < 6)
    {
        Thread.Sleep(1);
    }

    if (Hcom.BytesToRead >= 6)
    {
         Hcom.Read(Resoursedata, 0, 6);
         if (Resoursedata[3] == (byte)0x01)
    {
         while (Hcom.BytesToRead < 7)
         {
             Thread.Sleep(5);
         }
         if (Hcom.BytesToRead >= 7)
         {
             byte[] HReadbuffer = new byte[7];
             Hcom.Read(HReadbuffer, 0, 7);
             DeviceHandler._HPcmToAmbeBufferQueue.SendMsg(HReadbuffer);
         }
    }
    else if (Resoursedata[3] == (byte)0x02)
    {

         while (Hcom.BytesToRead < 320)
         {
              Thread.Sleep(5);
         }

              byte[] HReadbuffer = new byte[320];
              Hcom.Read(HReadbuffer, 0, 320);
              DeviceHandler._HAmbeToPcmBufferQueue.SendMsg(HReadbuffer);
    }
    else
    {
        Log.Error("BytesToRead error");
        Hcom.DiscardInBuffer();
    }
}

但测试时发现这种方式在遇到串口数据过大时会导致CPU占用率过高

之后更改为:

void H_Decode_com_DataReceived(object sendr, SerialDataReceivedEventArgs e)
        {
            int readByte = Hcom.BytesToRead;
            byte[] Resoursedata = new byte[13];
            if (readByte >= 13)
            {
                if (step == 0)
                {
                    Hcom.Read(Resoursedata, 0, 6);
                    if (Resoursedata[3] == (byte)0x01)
                    {
                        byte[] HReadbuffer = new byte[7];
                        Hcom.Read(WTReadbuffer, 0, 7);
                        DeviceHandler._HPcmToAmbeBufferQueue.SendMsg(HReadbuffer);
                    }
                    else if (Resoursedata[3] == (byte)0x02)
                    {
                        step++;
                    }
                }
                else if (step > 0)
                {
                    if (readByte >= 320)
                    {
                        byte[] HReadbuffer = new byte[320];
                        Hcom.Read(HReadbuffer, 0, 320);
                        DeviceHandler._HAmbeToPcmBufferQueue.SendMsg(HReadbuffer);
                        step = 0;
                    }
                }
            }
        }

因为C# serialport 提供的DataReceived,当触发了事件后就会调用事件函数,不论之前那个有没有处理完,所以每次调用事件函数时一定要保证快速的执行完,防止下次的触发事件在上一次还没执行完就又开始了。所以最后改为每次只检查串口接收缓冲区中存储的数据量,不在那里等待,直到满足数量要求后再取出来。

发布了16 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Hilaph/article/details/101672672
今日推荐