【问题标题】:Multithreading and Listening Serial Port多线程和监听串口
【发布时间】:2013-07-26 01:10:36
【问题描述】:

假设我想从串口接收一些数据。对 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 有自己的线程,我不应该从这个线程修改 UI,除非使用 BeginInvoke。但是,我注意到在一段时间内 UI 无论如何都会变得无响应。

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

【问题讨论】:

    标签: c# multithreading visual-studio-2010 threadpool


    【解决方案1】:

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

    DataReceived 事件肯定可以帮助您避免冻结 UI。您的问题中的提示太少,无法知道您的真正问题可能是什么。一个问题可能是过于频繁地使用 Control.BeginInvoke(),导致 UI 线程充斥着调用请求,因此它无法完成其常规职责。就像响应输入和绘画一样。解决方法是减少调用频率,您只需要让人类的眼睛保持快乐,它们的工作速度不会那么快。缓冲接收到的数据,保持 UI 的输出量合理,这样人们实际上可以看到的不仅仅是模糊。

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

    【讨论】:

    • 那意味着我不能调用 DataRecieved 中的其他函数来更新我的 UI。此外,每次收到消息时我都无法执行 Thread.Start() ,我该怎么办?
    • @Hans 解释得很清楚,这就是我给他 +1 的原因。与“多线程”中的许多答案不同,他的回答恰到好处。不要使用调用()。不要过度 BeginInvoke 并用 Windows 消息淹没 GUI 输入队列。不要不断地创建/启动/终止/销毁线程。如果您绝对需要在另一个线程中处理串行数据,请使用 BlockingCollection 队列将数据排队。
    猜你喜欢
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多