从C#中的另一个线程更新GUI - 是否更改回主线程?

时间:2013-05-21 10:51:07

标签: c# winforms

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

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

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

2 个答案:

答案 0 :(得分:3)

实际上,最简单的方法是

Invoke(new MethodInvoker(DoSomething));

如果你肯定从另一个线程调用它,即。如果你知道,那InvokeRequired将永远是真的。

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

答案 1 :(得分:0)

当然可能......你可以使用名为Dispatcher的类(System.Windows.Threading)。这个类的主要目的是在线程上发送“请求/调用”...对于gui线程,所有控件都有这样的调度程序实例。您可以将此实例作为窗口的成员找到,例如......

问题是您使用调度程序alraedy(在您发布的代码中)以某种方式...如果您在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之间的层。