如何高效接收不定长度的串口数据?(.NET Framework 4.6)
不定长度串口数据接收优化方案
现有实现及问题
我在while循环中实现了一种串口数据消息接收方法,每条消息长度在100-2048字节之间,多数约为1000字节。现有实现代码如下:
public int RecvSerialData(ref byte[] respBuf, int delay) { var recvBuf = new byte[2048]; var count = m_serial.BytesToRead; if (count > 0) { var sw = new Stopwatch(); sw.Restart(); while (sw.ElapsedMilliseconds < delay) { } count = m_serial.BytesToRead; m_serial.Read(recvBuf, 0, count); // Do something with respBuf return count; } return -1; }
当前核心问题是通信协议未包含消息长度字段,无法获知每条消息的准确长度。因此传入延迟参数时陷入两难:延迟过长会浪费大量时间,过短则可能导致消息接收不完整。
补充说明
- 客户端需等待我方回复前一条消息后才会发送下一条,因此即使设置很长的延迟,也不会接收到下一条消息。
- 实际测试显示,设置30ms延迟时,接收所有消息耗时超65秒,但能完整接收;设置5ms延迟时,耗时不足20秒,但部分消息接收不完整引发问题。
- 项目基于.NET Framework 4.6的WinForm应用。
协议格式
- Host(1字节,固定为0x02)
- Step(1字节,当前固定为0x35)
- InfoA(1字节)
- InfoB(2字节)
- ACK/NAK(1字节)
- Error Code(4字节)
- InfoC(2字节)
- Body(0-2000字节)
Info区域用于传输客户端信息,类似Host和Step,无长度或CRC字段。
优化后的实现方案
我找到了一个较好的方案,虽不完美但足以满足需求,代码如下:
public int RecvSerialData(ref byte[] respBuf) { var recvBuf = new byte[2048]; var count = m_serial.BytesToRead; if (count > 0) { var offset = 0; m_serial.Read(recvBuf, offset, count); offset += count; while(true) { count = m_serial.BytesToRead; if(count == 0) { break; } m_serial.Read(recvBuf, offset, count); offset += count; Thread.Sleep(5); } // Do something with respBuf return offset; } return -1; }
该方案对多数数据仅需休眠5ms或10ms,效果符合预期。
内容的提问来源于stack exchange,提问作者WangDaChui
相关产品推荐
相关产品推荐

