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) に初期化されます

クラスの参照ソースSerialStream1343 行目で、実際に次のことがわかります。

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 に答える