2013-07-25 139 views
0

假设我想从串口接收一些数据。使用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。但是,我注意到,在一段时间内,用户界面将无法响应。

所以这是我的问题。调用port_DataReceived中的新线程将是一个坏主意? 我想接收数据并在另一个线程中处理接收到的数据,但是mythread.Start()放在哪里?我不能一直开始它,我只是想让它知道何时在收到数据后独立运行。根据MSDN,中止的线程不能再次启动。把Thread.Sleep冻结我的用户界面。

回答

2

你误会发生了什么事情。 SerialPort.ReadLine()做不是使用线程。它是在另一个线程上运行的DataReceived事件处理程序。必要的,以便SerialPort可以尽快通知您的代码有关收到的数据,而无需等待您的UI线程闲置。这确实意味着你不能直接从你的事件处理程序更新你的UI,无论如何你会得到一个InvalidOperationException。

DataReceived事件当然可以帮助您避免冻结您的UI。你的问题中提示太少,不知道你真正的问题可能是什么。有一个问题可能是经常使用Control.BeginInvoke(),用调用请求泛滥UI线程,因此它不会执行常规任务。就像回应输入和绘画一样。解决这个问题的方法是简单地调用次数少一些,你只需要让人类的眼睛快乐起来,而且不会那么快。缓冲接收到的数据,保持输出到您的UI的合理数量,这样人们实际上可以看到的不仅仅是模糊。

另一个常见问题是死锁,它会永久冻结你的程序。使用调试器很容易诊断,您会看到程序停留在SerialPort.Close()调用中。当您使用Control.Invoke()而不是Control.BeginInvoke()时会发生这种情况。不要使用Invoke()。

+0

然后,这意味着我不能调用DataRecieved内的其他函数来更新我的UI。此外,我不能每次收到一条消息时都做Thread.Start(),那我该怎么办? – SpcCode

+1

@Hans已经很清楚地解释了,这就是我给他+1的原因。与“多线程”中的许多答案不同,他只是在点对点。不要使用Invoke()。不要过度开始使用Windows消息调用GUI并将其输入队列。不要连续创建/开始/终止/销毁线程。如果您绝对需要处理另一个线程中的串行数据,请使用BlockingCollection队列将数据排队。 –