SerialData.Eof情况

Jon*_*art 9 c# .net-4.0

在我的SerialPort.DataReceived事件处理程序中,我正在检查SerialData.Eof:

void DataReceived(object sender, SerialDataReceivedEventArgs e) {
    if (e.EventType == SerialData.Eof)
        throw new NotImplementedException("SerialData.Eof");
    // ... Read
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,在我的整个开发过程中,我从未遇到过这种异常.但今天,当处理不同的协议时,它就会受到影响.

我的问题是,究竟是什么SerialData.Eof意思?MSDN说:

收到文件结束字符并将其放入输入缓冲区.

我正在处理二进制数据.什么是"文件结束字符"?


这篇MSDN论坛帖子说明了这一点

DCB.EofChar成员始终初始化为0x1A(Ctrl + Z)

参考源SerialStream类,在1343线,我们看到的确是:

dcb.EofChar = NativeMethods.EOFCHAR;
Run Code Online (Sandbox Code Playgroud)

并在Microsoft.Win32.NativeMethods:

internal const byte EOFCHAR = (byte) 26; 
Run Code Online (Sandbox Code Playgroud)

那么这是否意味着我的设备发送一个0x1A字节,我会得到一个SerialData.Eof事件?如果是这种情况,我应该完全停止测试吗?

Han*_*ant 10

我在MSDN帖子中的原始分析是正确的.但是,参考源从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;
Run Code Online (Sandbox Code Playgroud)

呃,他们使用DCB的EvtChar设置来检测Ctrl + Z. 这是一个非常糟糕的想法,因为没有办法改变它,并且0x1a字节值肯定会出现在二进制协议中.在实践中,这几乎总是有一个好的结局,因为事件发生时会有一些东西需要阅读.然而,现在有一个竞争条件可以触发另一个事件,这次是SerialData.Chars,自上一个事件以来没有任何内容可以读取所有字节.这将使Read()调用块直到一个字节可用.这通常可以解决,但会增加Close()调用死锁的几率.慢性SerialPort问题.

处理这个问题的正确方法是:

void DataReceived(object sender, SerialDataReceivedEventArgs e) {
    if (e.EventType == SerialData.Eof) return;
    // ... Read
}
Run Code Online (Sandbox Code Playgroud)

  • Ctrl+Z 是传统的文本文件结束标记。可以追溯到 CP/M,这是一个很有影响力的早期操作系统。例如,对于与 COM 端口连接的打印机来说,Ctrl+Z 告诉它预计不会有更多数据到达,并且打印作业已完成。理论上来说。我从未见过它像今天这样用于串行端口的实际用途。 (2认同)