C#Windows窗体应用程序 – 从另一个线程AND类更新GUI?

我搜索了很多,但我似乎无法找到与我的具体问题有关的任何内容。

我希望能够从另一个类(SocketListener)更新我的MainUI表单,并且我有一个处理网络的线程(clientThread)。 现在我可以从网络线程运行简单的输出,例如写入调试器输出和创建MessageBox。

但我真正想做的是能够调用clientThread中的代码,该代码将在我的MainUI实例上执行操作。 我怎样才能做到这一点?

此外,如果有人想要代码的特定部分,那么我可以发布它,以帮助您更好地理解我的要求。

最好的祝福!

检查Control类的InvokeRequired ,如果是,则调用Invoke并传入一个委托(通常是匿名方法),该委托在客户端的线程上执行您想要执行的操作。

例:

 public void DoWork(Form form) { if (form.InvokeRequired) { // We're on a thread other than the GUI thread form.Invoke(new MethodInvoker(() => DoWork(form))); return; } // Do what you need to do to the form here form.Text = "Foo"; } 

是的,您可以在类中添加一个构造函数,该构造函数将MainUIforms作为参数。 这是快速的方法,但它引入了从类到MainUI的“向后”依赖,理论上,不需要依赖。

作为替代方案,我建议在您的类中添加一个公共事件,然后MainUI表单可以订阅。 当您的类需要更新MainUI(或MainUI中的控件)时,该类只会“引发”该事件。 这将调用它在订阅时注册的MainUI方法。 因为它已经是MainUI表单的一种方法,所以你要做的就是更新表单上的相应控件,确保考虑每个控件的InvokeRequired属性。

在这样做时,这是我在所有代码中使用的构造。

 class NetworkEventArgs : EventArgs { /* defined class here */ } private void NetworkEventHandler(object sender, NetworkEventArgs e) { Invoke( ( MethodInvoker ) delegate { myTextBox.Text = e.Message; } } 

我的评论基于这里的博客文章。 我没有让这种方法让我失望,所以我认为没有理由通过递归检查InvokeRequired属性来使我的代码复杂化。

您可以在clientThread类中定义一个事件

当clientThread需要知道mainform做某事(比如更新某些控件状态)时,你应该在mainform中处理它,你应该触发事件

所以mainform从事件中获取参数并调用更新函数