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

时间:2011-02-08 00:06:13

标签: c# .net winforms multithreading

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

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

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

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

祝你好运!

3 个答案:

答案 0 :(得分: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";
}

答案 1 :(得分: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属性来使我的代码复杂化。

答案 2 :(得分:0)

您可以定义clientThread类的事件

并在mainform中处理它 当clientThread需要知道mainform做某事时(比如更新一些控制状态) 你应该开火活动

因此mainform从事件中获取参数并调用更新函数

相关问题