2011-02-08 50 views
8

我搜查了一吨,但我似乎无法找到与我的具体问题有关的任何事情。C#Windows窗体应用程序 - 从另一个线程和类更新GUI?

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

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

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

此致敬礼!

回答

17

检查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"; 
} 
+0

由于我处于与UI不同的类中,因此如何获取指向当前正在运行的窗体以将其传递给DoWork的变量“form”? – 2011-02-08 00:18:52

+0

对于这种样板文件,不会有一些AutoProperty类语法糖好吗? – MusiGenesis 2011-02-08 00:20:38

4

是的,你可以添加一个构造函数类,是以MainUI形式作为参数。这是实现它的快速方法,但它从您的类向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; 
    } 
} 

我已经在此博客上的文章here上。我没有这种方法让我失望,所以我没有理由将我的代码与InvokeRequired属性的递归检查复杂化。

0

您可以自定义事件的clientThread类

,并在MainForm的 处理它时clientThread需要知道的MainForm做一些事情(如更新一些控制状态) 你应该火灾的事件

这样的MainForm得到来自事件和调用更新函数的参数

相关问题