假设我想从串口接收一些数据。使用块调用serial.ReadLine()并使用以下事件。
private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
var port = (SerialPort)sender;
string line = port.ReadLine();
// PROCESS DATA Somewhere else
}
我正在从不同的来源阅读并且所有人都说serial.ReadLine有自己的线程,除非使用BeginInvoke,否则我不应该从这个线程修改UI。但是,我注意到在一段时间内,UI无论如何都会变得无法响应。
所以这是我的问题。在port_DataReceived中调用一个新线程会是一个坏主意吗? 我想在另一个线程中接收数据并处理接收到的数据但是mythread.Start()在哪里放呢?我无法一直启动它只是想让它知道何时在收到数据后独立运行。并且根据MSDN,中止的线程无法再次启动。放入Thread.Sleep会冻结我的UI。
答案 0 :(得分:2)
你误解了发生的事情。 SerialPort.ReadLine()不使用线程。它是您在另一个线程上运行的DataReceived事件处理程序。必要时,SerialPort可以尽快通知您的代码有关收到的数据,而不必等待您的UI线程空闲。这确实意味着您无法直接从事件处理程序更新UI,无论如何都会遇到InvalidOperationException。
DataReceived事件当然可以帮助您避免冻结UI。你的问题提示太少,无法知道你的真正问题是什么。一个问题可能是经常使用Control.BeginInvoke(),使用调用请求充斥UI线程,因此它无法执行常规任务。喜欢回应输入和绘画。解决这个问题的方法是简单地调用,你只需要保持人眼的快乐,而不是那么快。缓冲接收的数据,保持UI的输出量合理,这样人类实际上可以看到的不仅仅是模糊。
另一个常见问题是死锁,它将永久冻结您的程序。使用调试器很容易诊断,你会看到你的程序卡在SerialPort.Close()调用上。当您使用Control.Invoke()而不是Control.BeginInvoke()时会发生这种情况。不要使用Invoke()。