简体   繁体   English

C#跨线程操作无效,2个控件和2个单独的线程

[英]C# cross-thread operation not valid, 2 controls and 2 separate threads

Here's a simplified example of what I'm trying to do: 这是我要执行的操作的简化示例:

I have 2 controls MyControl c and Panel p . 我有2个控件MyControl cPanel p p is created in the main GUI thread as normal, but I want c to be created in a background thread, because it takes awhile and I don't want to freeze the GUI. p是在GUI主线程中正常创建的,但是我希望c在后台线程中创建,因为这需要一段时间,而且我不想冻结GUI。 How can I add c to p.Controls ? 如何将c添加到p.Controls If I do it in this.Invoke it throws an exception for c , and if I do it from the background thread it throws an exception for p . 如果我在this.Invoke执行此操作,它将引发c的异常,如果我从后台线程执行,则将引发p的异常。

Or is it that I really shouldn't be creating GUI elements outside of the main GUI thread? 还是我真的不应该在主GUI线程之外创建GUI元素?

Or is it that I really shouldn't be creating GUI elements outside of the main GUI thread? 还是我真的不应该在主GUI线程之外创建GUI元素?

Yes, this is basically the problem. 是的,这基本上是问题所在。 Most controls have thread affinity, and must be created within the user interface thread. 大多数控件具有线程关联性,并且必须在用户界面线程中创建。

Typically, the way to handle this is to move the "work" that is causing the control creation to be slow onto a background thread, but still create the control on the UI thread. 通常,处理此问题的方法是将导致控件创建缓慢的“工作”移到后台线程上,但仍在UI线程上创建控件。 You'd then use Control.Invoke or Control.BeginInvoke to update the information in the UI once the slow work was completed. 一旦缓慢的工作完成,您就可以使用Control.Invoke或Control.BeginInvoke来更新UI中的信息。

For example, if you're loading a set of data from some external source, you can create the control, and start a background thread to load the data. 例如,如果要从某个外部源加载一组数据,则可以创建控件并启动后台线程以加载数据。 Once the data is loaded, you can then update the control to reflect it. 一旦数据被加载,你可以更新控制,以反映它。 This will cause it to stay responsive the entire time. 这将导致它始终保持响应状态。

It may be that your control does not take a long time to create; 可能是您的控件创建时间并不长。 rather it takes a long time to get its data. 而是需要很长时间才能获取其数据。 In that case, consider creating a control that can display it UI while it is being populated. 在这种情况下,请考虑创建一个可以在填充UI时显示其UI的控件。 Then you can create the control in your main thread, populate it in a background thread, and give your users a better experience. 然后,您可以在主线程中创建控件,将其填充到后台线程中,并为用户提供更好的体验。

Use background thread to do what it has to do, and then signal somehow ( bool _backgroundCompleted as a trivial example) that c is ready to be created. 使用后台线程执行它必须做的事情,然后以某种方式发出信号( bool _backgroundCompleted作为一个简单的示例),表明已准备好创建c

Create c from Timer that will fire periodically and do nothing until _backgroundCompleted is set, then create c , then kill the timer. Timer创建c ,它将定期启动,并且在设置_backgroundCompleted之前不执行任何_backgroundCompleted ,然后创建c ,然后_backgroundCompleted计时器。

It might be 'ugly', but it will work and will remain simple. 它可能是“丑陋的”,但是它将起作用并且将保持简单。

Forms.Timer , if you are asking ;) Forms.Timer ,如果您要求;)

And yeah, NEVER ever mess with multiple threads on the same form. 是的,永远不要搞乱相同形式的多个线程。 You can have several forms on several threads, but to do that, you have to first RUN a new thread, then create a form ON it. 您可以在多个线程上拥有多个表单,但是要这样做,您必须首先运行一个新线程,然后在其上创建一个表单。 It will have its own message loop, and will do fine. 它将有自己的消息循环,并且会很好。

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

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