简体   繁体   English

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

[英]C# Windows Forms Application - Updating GUI from another thread AND class?

I've searched a ton, but I can't seem find anything relating to my specific problem. 我搜索了很多,但我似乎无法找到与我的具体问题有关的任何内容。

I want to be able to update my MainUI form from another class (SocketListener) and within that I have a thread that handles the networking (clientThread). 我希望能够从另一个类(SocketListener)更新我的MainUI表单,并且我有一个处理网络的线程(clientThread)。 Right now I can run simple outputs from the networking thread such as writing to the debugger output and creating a MessageBox. 现在我可以从网络线程运行简单的输出,例如写入调试器输出和创建MessageBox。

But what I really want to do is be able to invoke code from the clientThread that will do things on my MainUI instance. 但我真正想做的是能够调用clientThread中的代码,该代码将在我的MainUI实例上执行操作。 How can I do this? 我怎样才能做到这一点?

Also, if anyone wants specific portions of the code then I can post it to help give you a better understanding of what I'm asking. 此外,如果有人想要代码的特定部分,那么我可以发布它,以帮助您更好地理解我的要求。

Best regards! 最好的祝福!

Check the InvokeRequired of the Control class, and if it's true, then call the Invoke and pass in a delegate (usually an anonymous method) that does what you want to do on the client's thread. 检查Control类的InvokeRequired ,如果是,则调用Invoke并传入一个委托(通常是匿名方法),该委托在客户端的线程上执行您想要执行的操作。

Example: 例:

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";
}

Yes, you could add a constructor to your class that takes the MainUI form as a parameter. 是的,您可以在类中添加一个构造函数,该构造函数将MainUI形式作为参数。 That is the quick way to do it, but it introduces a "backward" dependency from your class to the MainUI where, in theory, no dependency is required. 这是快速的方法,但它引入了从类到MainUI的“向后”依赖,理论上,不需要依赖。

As an alternative, I would suggest adding a public event to your class that the MainUI form could then subscribe to. 作为替代方案,我建议在您的类中添加一个公共事件,然后MainUI表单可以订阅。 When your class needs to update the MainUI (or controls within the MainUI), the class would simply "raise" the event. 当您的类需要更新MainUI(或MainUI中的控件)时,该类只会“引发”该事件。 This will call the MainUI's method that it registered at the time of subscription. 这将调用它在订阅时注册的MainUI方法。 Since it is a method of the MainUI form already, all you have to do is update the appropriate controls on the form, making sure to take the InvokeRequired property of each control into account. 由于它已经是MainUI表单的一种方法,您所要做的就是更新表单上的相应控件,确保将每个控件的InvokeRequired属性考虑在内。

And when doing that, here's the construct I've been using in all my code. 在这样做时,这是我在所有代码中使用的构造。

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

I've based this on the blog entry here . 我已经在博客条目基于此这里 I have not had this approach fail me, so I see no reason to complicate my code with a recursive check of the InvokeRequired property. 我没有让这种方法让我失望,所以我认为没有理由通过递归检查InvokeRequired属性来使我的代码复杂化。

you can define an event your clientThread class 您可以在clientThread类中定义一个事件

and handle it in mainform when clientThread needs aware mainform to do something(like update some control status) you should Fire the event 当clientThread需要知道mainform做某事(比如更新一些控件状态)时,你应该在mainform中处理它,你应该触发事件

so mainform gets paramter from event and invokes update function 所以mainform从事件中获取参数并调用更新函数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM