串口通信:轮询串口 vs 使用串口DataReceived事件

16

我正在审查我写的一些C# CF2.0串口通信代码。我不使用DataReceived事件,因为它不可靠。MSDN指出:

DataReceived事件不能保证为每个接收到的字节都会触发。使用BytesToRead属性确定缓冲区中还有多少数据需要读取。

我使用read()轮询端口,并有一个委托在读取数据时处理该数据。我还在某处读到过“轮询是糟糕的”(没有给出解释)。

除了通常的线程注意事项以外,你有什么想法为什么轮询可能是不好的?- 我有一个单独的线程(后台线程)轮询端口,在读取数据后该线程退出,经过测试运行良好。

3个回答

19

我理解的是,你可能会因为一个事件而获得多个字节,而不是每个字节都对应一个事件。但即使如此,我仍然期望在数据准备好时收到事件,并且不希望它完全“跳过”一些字节。

我一直使用这个事件,并没有遇到任何问题。


2
绝对的,这也是我的经验。 - Andy

9
传统智慧认为“轮询是不好的”,因为它经常会成为一个CPU绑定过程。如果使用阻塞I/O,则CPU在事件发生之前可用于其他进程。
话虽如此,通常可以设置事物,使得在没有字符可用时,轮询等待(短暂)超时后才返回。如果选择了适当的超时时间,则您的简单轮询循环使用的CPU时间显著减少,并且其他进程也有机会运行。
我从未使用C#的串口,但我要猜测文档所说的是
“The DataReceived event is not guaranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer.”
意思是您不能期望每个字符都触发一次事件。在某些情况下,它可能会传递带有多个字符的事件。只需在事件处理程序中检索所有可用字符即可。
编辑:在读取器线程上进行阻塞调用可能是总体上最好的答案。这不是轮询本身,因为线程被阻塞直到字符到达。如果需要实时处理数据而不是以固定大小的块处理数据,则可能需要调整缓冲区大小和一些串口设置。

1
谢谢,我猜这是有道理的。我的应用程序中,用户应该能够从设备中捕获值或手动输入值。当任何一种情况发生时,轮询线程都会退出,我不会阻塞CPU。 - sarsnake

3
我相信即使使用阻塞式的Read调用,底层串口驱动代码也是中断驱动的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接