How to use SerialPort class more reliably

how*_*ith 4 c# serial-port

I've been using the SerialPort class for a little while in an application that communicates with some external hardware that I've designed. During the debugging process of said hardware, I found a few things to be unreliable, and I recently stumbled across this which seems to be onto something.

I'm trying to implement this into my application, however I have two questions about receiving data...

So, in the article I linked, the author mentions that the DataReceived event is problematic, and shows a typical code sample of how it could be used...

port.DataReceived += port_DataReceived;

// (later, in DataReceived event)
try {
    byte [] buffer = new byte[port.BytesToRead];
    port.Read(buffer, 0, buffer.Length);
    raiseAppSerialDataEvent(buffer);
}
catch (IOException exc) {
    handleAppSerialError(exc);
}
Run Code Online (Sandbox Code Playgroud)

And then what the author considers to be the correct method is shown...

byte[] buffer = new byte[blockLimit];
Action kickoffRead = null;

kickoffRead = delegate {
port.BaseStream.BeginRead(buffer, 0, buffer.Length, 
        delegate (IAsyncResult ar) {
            try {
                int actualLength = port.BaseStream.EndRead(ar);
                byte[] received = new byte[actualLength];
                Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
                raiseAppSerialDataEvent(received);
            }
            catch (IOException exc) {
                handleAppSerialError(exc);
            }
            kickoffRead();
        }, null);
    };
    kickoffRead();
Run Code Online (Sandbox Code Playgroud)

BaseStream.BeginRead我的问题围绕着;的使用 在我的班级中,应该将读取数据的内容放在哪里?我的第一个想法是在DataReceived事件中,就像在第一个示例中展示如何不使用该类一样,SerialPort作者在评论中提到了代码在DataReceived事件中,但是对于显示更好方法的示例,作者没有提及在哪里代码应该是这样我以为他还是指事件DataReceived,但是后来作者提到DataReceived事件本身有问题,所以...?这里的任何指导都会很棒,如果很明显的话,我们深表歉意!

如果我没有提到任何对试图回答这个问题的人有益的事情,那么请务必让我知道。预先感谢您的任何指导和/或反馈!

Mui*_*uis 5

它是一个递归函数,因此您在打开端口后仅调用此代码一次,并且它将继续重复自身而不会阻止执行(或需要 DataReceived 事件处理程序)。

  • 我不知道谁对此投了反对票,但 Muls 是正确的(+1)。我应该知道,我是那篇博客文章的作者。 (2认同)
  • 另请注意,这不是*真正的*递归,“BeginRead”块是从完成处理程序调用的,而不是从其自身调用,因此调用堆栈不会无限期增长。 (2认同)
  • @AysonBaxter:在终端异常之后(从串行端口根本不再可用的意义上来说,重试操作是没有希望的),您应该安排“kickoffRead()”不再被调用。这可以通过跟踪端口是否关闭并检查此标志,然后从回调返回而不调用“kickoffRead()”...或者简单地当您关闭端口时将“kickoffRead”委托设置为指向一个 no- op 函数如 `kickoffRead = delegate { };` (2认同)