简体   繁体   English

多线程和侦听串行端口

[英]Multithreading and Listening Serial Port

Lets say I want to receive some data from the serial port. 可以说我要从串行端口接收一些数据。 Using a block call for serial.ReadLine() and using the following event. 对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

} }

I was reading from different sources and all of they say that the serial.ReadLine has its own thread and I should not modify the UI from this thread unless using BeginInvoke. 我从不同的来源阅读,他们都说serial.ReadLine有它自己的线程,除非使用BeginInvoke,否则我不应该从此线程修改UI。 However, I notice that during some time the UI will become unresponsive anyway. 但是,我注意到一段时间后,UI仍然会变得无响应。

So here is my question. 所以这是我的问题。 Calling a new thread inside port_DataReceived will be a bad idea? 在port_DataReceived内部调用一个新线程是一个坏主意吗? I want to receive the data and process the received data in another thread however mythread.Start() where to put it? 我想接收数据并在另一个线程中处理接收到的数据,但是mythread.Start()放在哪里? I cannot be starting it all the time I just want it to know somehow when to run independently after receiving the data. 我无法一直启动它,只是希望它知道接收数据后何时独立运行。 And according to MSDN a aborted thread cannot be started again. 根据MSDN,中止的线程无法再次启动。 Putting Thread.Sleep is freezing my UI. 放置Thread.Sleep将冻结我的UI。

You misunderstand what is going on. 您误解了发生了什么。 SerialPort.ReadLine() does not use a thread. SerialPort.ReadLine() 使用一个线程。 It is your DataReceived event handler that runs on another thread. 是您的DataReceived事件处理程序在另一个线程上运行。 Necessary so that the SerialPort can notify your code about received data as quickly as possible without having to wait for your UI thread to go idle. 这是必需的,以便SerialPort可以尽快将接收到的数据通知您的代码,而不必等待UI线程空闲。 Which does indeed mean that you cannot directly update your UI from your event handler, you'll get an InvalidOperationException when you try anyway. 这确实意味着您不能直接从事件处理程序中更新UI,无论如何尝试都将收到InvalidOperationException。

The DataReceived event is certainly there to help you avoid freezing your UI. 当然,DataReceived事件可以帮助您避免冻结UI。 There are too few hints in your question to know what your real problem might be. 您的问题中没有太多提示可以知道您的真正问题是什么。 One issue could be using Control.BeginInvoke() too often, flooding the UI thread with invoke requests so it doesn't get around to doing its regular duties. 一个问题可能是过于频繁地使用Control.BeginInvoke(),在UI线程中充斥着调用请求,因此它无法正常工作。 Like responding to input and painting. 喜欢回应输入和绘画。 The workaround for that is to simply invoke less often, you only need to keep human eyes happy and they don't work that fast. 解决方法是简单地减少调用频率,只需要保持人眼愉悦,它们就不会那么快地工作。 Buffer the received data, keep the amount of output to your UI reasonable so a human can actually see more than a blur. 缓冲接收到的数据,使输出到UI的数量保持合理,这样人类实际上可以看到的不仅仅是模糊。

Another common issue is deadlock , it will permanently freeze your program. 另一个常见问题是死锁 ,它将永久冻结您的程序。 Easy to diagnose with a debugger, you'll see your program stuck on the SerialPort.Close() call. 使用调试器易于诊断,您会看到程序卡在SerialPort.Close()调用中。 This happens when you use Control.Invoke() instead of Control.BeginInvoke(). 当您使用Control.Invoke()而不是Control.BeginInvoke()时,会发生这种情况。 Don't use Invoke(). 不要使用Invoke()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM