代码神秘地在函数中间结束(serialport datareceived handler)

时间:2015-05-03 17:47:58

标签: c# wpf serial-port

我在C#代码中有一个SerialPort DataReceived事件处理程序:

void serPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    SerialPort sp = (SerialPort)sender;
    string indata = "";
    while (sp.ReadBufferSize > 0) {
        int bytes = sp.ReadBufferSize;
        char[] result = new char[bytes];
        sp.Read(result, 0, bytes);
        indata += new string(result).Replace("\0", "");
    }
    Dispatcher.Invoke((Action)(() => port1out.Text += indata + "\n"));
}

使用断点,我知道函数被调用,而循环正在执行,即使indata变量包含接收的数据,但是当while循环结束时,整个监听器结束。没有文字添加到port1out文本框中。我尝试在Dispatcher.Invoke ....之后(以及之前)添加无执行代码,使用断点并且它没有被执行 - 代码只是在while循环之后结束。 为什么?为什么不执行整个陈述?

1 个答案:

答案 0 :(得分:0)

丢弃DataReceived事件,而只是这样做:

void ReadFromPort(SerialPort p)
{
     Stream s = p.BaseStream;
     s.ReadTimeout = 20;
     // 1/50th of a second and 10 serial bits per byte
     byte[] buffer = new byte[p.BaudRate / 500];
     ReadSerialStream(s, buffer);
}

void async ReadSerialStream(Stream s, byte[] buffer)
{
     int bytesRead = await s.ReadAsync(buffer, 0, buffer.Length);
     string indata = Encoding.ASCII.GetString(
                              buffer.Take(bytesRead).Where(b => b != 0).ToArray());
     port1out.Text += indata + Environment.Newline;
     ReadSerialStream(s, buffer);
     // or use an infinite while loop. With async methods, recursion is safe
}

实际上正在进行读取将使虚拟串行端口实际上开始传输数据。如果您依赖DataReceivedBytesToRead,您的数据可能会卡在(例如)USB传输缓冲区中,并且永远不会到达串行端口对象。或者,您最终可能会为每个字节进行多次USB传输(首先报告"缓冲区不为空"标记,然后传输缓冲区内容)。 ReadAsync在所有级别都更有效率。此外,它在async / await范例内工作,直接在UI线程上接收串行事件,因此您不必混淆跨线程调用或同步访问内部数据结构。