SerialData.Eof情况
在我的SerialPort.DataReceived
事件处理程序中,我正在检查SerialData.Eof
:
void DataReceived(object sender, SerialDataReceivedEventArgs e) { if (e.EventType == SerialData.Eof) throw new NotImplementedException("SerialData.Eof"); // ... Read }
在我到目前为止的整个开发过程中,我从来没有遇到过这个例外。 但今天,当处理不同的协议时,它就会受到影响。
我的问题是, SerialData.Eof
究竟是什么意思? MSDN说:
收到文件结束字符并将其放入输入缓冲区。
我正在处理二进制数据。 什么是“文件结束字符”?
这篇MSDN论坛post说明了这一点
DCB.EofChar
成员始终初始化为0x1A(Ctrl + Z)
在SerialStream
类的引用源中,在第1343行,我们确实看到了:
dcb.EofChar = NativeMethods.EOFCHAR;
在Microsoft.Win32.NativeMethods
:
internal const byte EOFCHAR = (byte) 26;
那么这是否意味着我的设备发送一个0x1A字节,我将得到一个SerialData.Eof
事件? 如果是这种情况,我应该完全停止测试吗?
我在MSDNpost中的原始分析是正确的。 但是,参考源从SerialStream.cs中显示了答案:
dcb.EofChar = NativeMethods.EOFCHAR; //OLD MSCOMM: dcb.EvtChar = (byte) 0; // now changed to make use of RXFlag WaitCommEvent event => Eof WaitForCommEvent event dcb.EvtChar = NativeMethods.EOFCHAR;
呃,他们使用DCB的EvtChar设置来检测Ctrl + Z. 这是一个非常糟糕的想法,因为没有办法改变它,并且0x1a字节值肯定会出现在二进制协议中。 在实践中,这几乎总是有一个好的结局,因为事件发生时会有东西要读。 然而,现在有一个竞争条件可以触发另一个事件,这次是SerialData.Chars,自上一个事件以来没有任何内容可以读取所有字节。 这将使Read()调用块直到一个字节可用。 这通常可以解决,但会增加Close()调用死锁的几率。 慢性SerialPort问题。
处理这个问题的正确方法是:
void DataReceived(object sender, SerialDataReceivedEventArgs e) { if (e.EventType == SerialData.Eof) return; // ... Read }