10

在我的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 论坛帖子指出

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

在该课程的参考资料SerialStream中,在第 1343 行,我们确实看到:

dcb.EofChar = NativeMethods.EOFCHAR;

并在Microsoft.Win32.NativeMethods

internal const byte EOFCHAR = (byte) 26; 

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

4

1 回答 1

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;

呃,他们使用 DCB 的 EvtChar 设置来检测 Ctrl+Z。这是一个非常糟糕的主意,因为无法更改它并且 0x1a 字节值肯定会出现在二进制协议中。在实践中,这几乎总是有一个好的结果,因为当事件触发时会有一些东西可以阅读。然而,现在有一个竞争条件可以触发另一个事件,这次是 SerialData.Chars,因为上一个事件导致所有字节都被读取,所以没有什么可读取的。这将使 Read() 调用阻塞,直到一个字节可用。这通常可以解决,但确实增加了 Close() 调用死锁的几率。一个长期的 SerialPort 问题。

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

void DataReceived(object sender, SerialDataReceivedEventArgs e) {
    if (e.EventType == SerialData.Eof) return;
    // ... Read
}
于 2012-11-18T07:39:45.340 回答