【问题标题】:Update the GUI from another thread in C# - change back to the main thread or not?从 C# 中的另一个线程更新 GUI - 是否更改回主线程?
【发布时间】:2013-05-21 10:51:06
【问题描述】:

我知道从另一个线程更新标签的最简单方法是:

void DoSomething()
{
    if (InvokeRequired)
    {
        Invoke(new MethodInvoker(DoSomething));
    } else 
    {
        // Do Something
    }
}

我的问题是,是否可以代替需要从另一个线程更新 GUI 的 if 更改回主线程并从那里更新 GUI?

【问题讨论】:

  • 请更好地解释您的问题。你想完成什么?
  • it possible to change back to the main thread and update the GUI from there 这正是Invoke所做的。

标签: c# winforms


【解决方案1】:

其实最简单的方法是

Invoke(new MethodInvoker(DoSomething));

如果你确定从另一个线程调用它,即。如果您知道,那 InvokeRequired 将始终为真。

此外,您可以使用 WinForms 计时器来轮询例如文本字段的更改。此计时器在 GUI 线程中运行。如果每秒有数百个事件,这是一个很好的解决方案。或者至少“很多”。这样您就不需要太多切换到 GUI 线程(这总是需要相当长的时间)。

【讨论】:

    【解决方案2】:

    当然有可能……您可以使用名为 Dispatcher (System.Windows.Threading) 的类。此类的主要目的是在线程上分派“请求/调用”……对于 gui 线程,所有控件都可以使用此类分派器的实例。例如,您可以将此实例作为 Window 的成员...

    问题是您以某种方式使用调度程序(在您发布的代码中)......如果您在 Form 内部调用 Invoke,则使用此默认/gui调度程序。并且“IF”用于减少来自 gui 线程本身的调用次数。

    它的工作方式类似于“我在 ui 线程中吗?没有?然后给调度程序请求在 UI 线程上调用这个相同的方法!...我在 UI Thred 中吗?是的!好的,我正在做某事。”

    如果您 100% 确定调用此表单而不是 UI 线程,则可以丢弃该 IF 并直接调用调度程序。

        MyForm.Dispatcher.Invoke( mydelegate, params[] )
    

    或者使用一些 lambda 代替委托或 MethodInvoker ...

       MyForm.Dispatcher.BeginInvoke( (Action)(()=>{ textbox.text = result; }), null);
    

    而且……您可以存储(例如在 form.load 事件中)对 UI Dispatcher 的引用以在不同的类中使用(一些工作类在其他类上做事)

    如果您创建一些更大的 UI 内容,我对更好的 UI 和更易于处理的内容的建议是:...考虑对 WPF 和 MVVM 模式和属性更改通知进行一些研究......它将为您提供非常强大的工具在数据、工作线程和 UI 之间具有“自我更新”和非常可扩展的 UI 和层。

    【讨论】:

    • Dispatcher 是 WPF,而不是 WinForms!
    • 是的,WinForms 控件没有作为成员公开调度程序。但是,即使在 WinForm 中,您仍然可以使用调度程序。
    • 它只是用于在线程上规划“作业”的类。使用 Dispatcher.CurrentDispatcher() 您可以检索耦合到当前线程的实例。可能需要引用 WindowsBase。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    相关资源
    最近更新 更多