10

In my SerialPort.DataReceived event handler, I am checking for SerialData.Eof:

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

In my entire development up to this point, I have never hit this exception. But today, when working on a different piece of the protocol, it hit.

My question is, what exactly does SerialData.Eof mean? MSDN says:

The end of file character was received and placed in the input buffer.

I'm dealing with binary data. What is the "end of file character"?


This MSDN Forum Post states that

the DCB.EofChar member always gets initialized to 0x1A (Ctrl+Z)

In the reference sources for the SerialStream class, at line 1343, we see that indeed:

dcb.EofChar = NativeMethods.EOFCHAR;

And in Microsoft.Win32.NativeMethods:

internal const byte EOFCHAR = (byte) 26; 

So does this mean anytime my device sends an 0x1A byte, that I will get a SerialData.Eof event? If that is the case, should I just stop testing for it altogether?

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • Take a look at this StackOverFlow post I also can't see in your example where you are even reading byes if there are any to be read http://stackoverflow.com/questions/466474/how-do-i-use-datareceived-event-of-the-serialport-port-object-in-c – MethodMan Sep 18 '12 at 19:38
  • 1
    @DJKRAZE Thanks, but I know how to use the `DataReceived` event, my code is working just fine. I'm not sure why this was downvoted. I'm simply asking what **exactly** `SerialData.Eof` means. – Jonathon Reinhart Sep 18 '12 at 20:02
  • 1
    Up-voted. I would interpret `EOF` event as stream termination, i.e. what ever is sending you data has either finished or has encounted an error. I'm not 100% certain on this and as such posting as a comment than an answer. Interested in finding out as I intend to do some serial port work soon. – Dennis Sep 18 '12 at 20:54
  • Since the data being sent by my device contains some contains lots of data determined by user timing, it's safe to say that the bytestream is psuedo-random. I'm seeing this `SerialData.Eof` only sometimes, and twice the data received **before** the event has contained a `1A` byte. So I think it is safe to simply ignore `DataReceived` if `e.EventType == SerialData.Eof`. Unless of course your device *actually* sends a `1A` at the end of its stream. – Jonathon Reinhart Sep 18 '12 at 21:26
  • Leaving this ever-so-slightly related link here: [.NET SerialPort Woes](https://zachsaw.blogspot.com/2010/07/net-serialport-woes.html) – Jonathon Reinhart Feb 01 '19 at 13:49

1 Answers1

11

My original analysis in that MSDN post was correct. However, the reference source reveals the answer, from 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;

Ugh, they used the DCB's EvtChar setting to detect a Ctrl+Z. This was a Really Bad Idea, given that there's no way to change it and a 0x1a byte value can certainly appear in a binary protocol. In practice this almost always comes to a good end since there will be something to read when the event fires. Nevertheless, there's now a race condition that can fire another event, this time SerialData.Chars, with nothing to read since the previous event caused all bytes to be read. Which will make the Read() call block until a byte is available. Which usually works out but does increase the odds that the Close() call deadlocks. A chronic SerialPort problem.

The proper way to deal with this is:

void DataReceived(object sender, SerialDataReceivedEventArgs e) {
    if (e.EventType == SerialData.Eof) return;
    // ... Read
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks a lot - I'm glad to see this re-visited. I think (source code is not in front of me right now) I simply commented out the check of `EventType` altogether. But that implies that I am calling `Read()` on *both* events (`Chars` and `Eof`). And now that you mention it, I think I also had code that said "if zero bytes to read, bail"... which is exactly what you said would happen. So perhaps if I ignore the `Eof` case and return (as you have), all will be good. I will try this Monday. – Jonathon Reinhart Nov 18 '12 at 09:47
  • Thanks Hans, but a little bit more explanation would be helpful here. What was this EOF event implmented for? In your code you simply ignore it, but in what cirumstance may it be useful? Does it mean that each 0x1A byte in a binary stream fires this event? Is this 0x1A byte then missing in the received data bytes? – Elmue Nov 22 '18 at 20:59
  • 2
    Ctrl+Z was the traditional end-of-file marker for text. Goes all the way back to CP/M, an early operating system that was influential. Could matter for, say, a printer that is connected with a COM port, Ctrl+Z tells it that no more data is expected to arrive and the print job is done. Theoretically. I have never seen a practical usage of it for serial ports the way they get used today. – Hans Passant Nov 22 '18 at 21:07