如何从另一个类更新Windows窗体GUI?

时间:2010-07-12 06:21:32

标签: c# winforms multithreading

如何从另一个创建GUI而不是创建线程的类更新win表单控件(例如标签,进度条)? (例如,Program.cs的事件处理程序)

我发现了几篇关于使用Invoke()方法从另一个线程更新GUI的帖子,但到目前为止我发现的只有在代码与表单编写在同一个类中时才有效

http://www.yoda.arachsys.com/csharp/threads/winforms.shtml

2 个答案:

答案 0 :(得分:8)

您需要在表单上调用Invoke方法。例如:

private void someMethod() {
    myOtherForm.Invoke(new MethodInvoker(delegate() {
        // update things in myOtherForm here
    }));
}

如果在返回方法之前不需要完成更新,则应使用BeginInvoke而不是Invoke

答案 1 :(得分:5)

嗯,这里有两个不同的问题:

  • 从其他班级更新用户界面
  • 从其他线程更新UI

两者几乎完全正交。一旦你孤立地解决了每一个问题,你就可以把它们放在一起了。

如果有很好理解的方式需要更改UI(例如更新状态栏中的文本或类似的东西),我会在UI类本身中编写方法来执行此操作,并调用这些方法来自其他班级。或者,您可以公开UI的各个控件 - 最好通过属性 - 然后以正常方式使用Control.Invoke,例如。

MethodInvoker action = () => form.StatusLabel.Text = "Finished";
form.BeginInvoke(action);

只要你在与你触摸的所有控件相同的线程上“生活”的控件上调用Invoke,你使用哪一个都无关紧要......所以另一种选择可能是:< / p>

Label label = form.StatusLabel;
MethodInvoker action = () => label.Text = "Finished";
label.BeginInvoke(action);

这里的一个区别是,在后面的代码中,StatusLabel属性正在工作线程中进行评估 - 如果您的UI正在更改它以引用竞争条件,可能导致竞争条件不同时间的不同标签。我通常更喜欢第一种方法。

(我同意icktoofay关于BeginInvoke更可取的评论,除非你真的需要等待,顺便说一下......虽然你需要注意对匿名函数捕获的任何变量的更改。)< / p>