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