在终止任务之前正确使用 InvokeRequired [英] Proper usage of InvokeRequired before terminating a task

查看:52
本文介绍了在终止任务之前正确使用 InvokeRequired的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发与串行端口相关的应用程序.在使用 SerialPortDataReceived 事件时,我需要用接收到的字节更新文本框:

I am working on a serial port related application. While using DataReceived event of SerialPort I need to update a textbox with the received bytes:

private void Connection_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    ledReceive.On = true;

    var data = Connection.ReadExisting();

    _readBuffer.Add(data);
    Invoke(new EventHandler(AddReceivedPacketToTextBox));       
}

所以我使用 Invoke 来更新文本框.但是有一个很大的问题.当我尝试关闭连接时,我的 UI 被冻结,我认为这是因为 Invoke 可能正在做一些事情.

So I use Invoke to update the textbox. But there is a big problem. When I try to close connection, my UI gets freezed, I think this is becase Invoke is doing somehing perhaps.

一个朋友说我应该使用RequiredInvoke,但我不知道他到底在说什么.如何在不弄乱调用和 UI 线程的情况下关闭连接?

A friend said I should use RequiredInvoke, but I have no idea what he ment really. How can I close the connection without messing up the invoke and UI thread?

这是我的关闭方法:

private void DisconnectFromSerialPort()
{
    if (Connection != null && Connection.IsOpen)
    {
        Connection.Close();
        _receivedPackets = 0; //reset received packet count
    }
}

推荐答案

我不完全确定,但我猜当您关闭连接时正在更新您的 UI 的线程被删除,这可以解释为什么它冻结.但如果不深入研究您的所有代码,我就无法确定.

I'm not fully sure, but I would guess that the thread that is updating your UI is removed when you close your connection, which could explain why it freeze. But I can't be sure without digging in all your code.

如果尝试访问您的元素的线程不是您的 UI 原生的,则 InvokeRequired 返回 true.或者,如果您更喜欢 MS 解释:

InvokeRequired return true if the thread trying to access your element isn't native to your UI. Or if you prefer MS explaination:

    // Summary:
    //     Gets a value indicating whether the caller must call an invoke method when
    //     making method calls to the control because the caller is on a different thread
    //     than the one the control was created on.
    //
    // Returns:
    //     true if the control's System.Windows.Forms.Control.Handle was created on
    //     a different thread than the calling thread (indicating that you must make
    //     calls to the control through an invoke method); otherwise, false.

还有一个基本的实现:

    public void ReceiveCall()
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new CallDelegate(ReceiveCall), new object[] { });
            return; // Important to not continue on this method.
        }

        // Whatever else this function is suppose to do when on the correct thread.
    }

Invoke 应该是您的函数所做的第一件事,以防止该线程进入您的 UI 深处.现在,如果连接本身被确定在您的 UI 线程的边界内,它可能不会触发InvokeRequired".防止这种情况发生的一种方法是手动创建一个线程来更新未绑定到您的连接的 UI.

The Invoke should be the first thing your function does, to prevent that thread from entering deep in your UI. Now, if the connection itself is determined to be within the bounderies of your UI's thread, it probably won't trigger "InvokeRequired". One way to prevent this from happening, would be to manually create a thread that update your UI that isn't bound to your connection.

我在时钟更新多个 UI 元素的渲染时遇到了类似的问题.时钟可以正常工作,但会挂起",直到所有 UI 都完成渲染,这在大量 UI 的情况下意味着它会跳过它的下一个滴答声.

I had a similar problem with a clock updating the rendering of multiple UI element. The clock would work fine, but would "hang" until all the UI is done rendering, which in case of a lot of UI would mean it would skip it's next tick.

     Thread updateUI = new Thread(updateUIDelegate);
     updateUI.Start();

这样,我的时钟(或你的连接)将启动一个独立的线程,它自己做它的事情.您可能还需要检查 Monitor 类或 lock 关键字,以防止线程冲突或使用相同变量的多个线程.

This way, my clock (or your connection) would start an independant thread that does its stuff on its own. You may also want to check the Monitor class or the lock keyword to prevent colliding threads or multiple threads using the same variables.

或者您可以阅读令人敬畏的答案,这可能比我的更有意义:关闭串口时是什么导致我的 UI 冻结?

Or you could read the awesome answer at, which probably make more sense than mine: What causes my UI to freeze when closing a serial port?

这篇关于在终止任务之前正确使用 InvokeRequired的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆