简体   繁体   English

C#-BackgroundWorker不断更新控件:错误!

[英]C# - BackgroundWorker Constantly Updating Control: Error!

I traditionally have a lot of trouble with BackgroundWorkers in C# for some reason; 传统上,由于某些原因,我在C#中使用BackgroundWorkers遇到很多麻烦; their concept really seems to stump me, so I'm hoping this is a fairly basic issue and something the can be corrected easily enough... 他们的概念确实让我感到难过,所以我希望这是一个相当基本的问题,并且可以很容易地纠正这些问题。

I have two forms that use .NET remoting to communicate back and forth. 我有两种使用.NET远程通讯来进行通讯的形式。 Right now, changing a setting on Form1 causes something to change on Form2 and that works great. 现在,更改Form1上的设置会导致Form2上发生某些更改,并且效果很好。 However, now I need to make the same thing work the other way (changing something on Form2 causes Form1 to update) and I can't do it the same way (I cannot, due to restrictions in the design, have Form2 send the change to Form1). 但是,现在我需要以另一种方式使同一事物工作(在Form2上进行更改会导致Form1进行更新),而我不能以相同的方式进行操作(由于设计方面的限制,我无法让Form2发送更改)到Form1)。 Right now, I'm trying to use a BackgroundWorker on Form1 to constantly call an 'Update()' method on each of the subcontrols (which are placed on Form1). 现在,我试图在Form1上使用BackgroundWorker不断在每个子控件(放置在Form1上)上调用“ Update()”方法。 Each of these controls have the means to grab the current state of their equalivalent settings from Form2 and update themselves (this works well; the 'Update()' method is already seen to be working on the initialization of Form1). 这些控件中的每一个都具有从Form2抓取​​其等效设置的当前状态并进行自我更新的方式(此方法很好;已经看到'Update()'方法正在Form1的初始化上起作用)。

Here's where my issue comes up. 这是我的问题所在。 I was unsure on how make the BackgroundWorker constantly call 'Update()' on each of the forms, so in my 'DoWork()' method, I have a "while(true)" loop and within that the BackgroundWorker calls the 'Update()' method of each subcontrol, then sleeps for a very short time, then repeats. 我不确定如何使BackgroundWorker在每个表单上不断调用“ Update()”,因此在我的“ DoWork()”方法中,我有一个“ while(true)”循环,并且在其中,BackgroundWorker调用了“ Update” ()'每个子控件的方法,然后睡眠很短的时间,然后重复。

Doing it this way, I get an "InvalidOperationException was unhandled by user code" error with details stating that "Cross-thread operation not valid: Control 'comboBox_BGColor' accessed from a thread other than the thread it was created on." 这样,我收到一个“ InvalidOperationException未由用户代码处理”错误,并详细说明“跨线程操作无效:从创建该线程的线程以外的其他线程访问控件'comboBox_BGColor'。” Now, I basically know what this means and I understand why it happened, however, I'm unsure what to do differently or how to change things to make it work as desired. 现在,我基本上了解了这意味着什么,并且知道了为什么会发生这种情况,但是,我不确定该做什么或如何更改这些东西以使其按预期工作。 Anyone have any tips on this or the way I'm using BackgroundWorker? 有人对这个或我使用BackgroundWorker的方式有任何提示吗? Thanks a lot for any information and for taking the time to read this! 非常感谢您提供任何信息,并抽出宝贵的时间阅读本文!

UI controls have thread affinity . UI控件具有线程关联性 You shouldn't touch the controls (for read or write) from any thread except the UI thread. 除了UI线程外,您不应触摸任何线程的控件(用于读取写入)。 If the BackgroundWorker is talking primarily to the UI, you would probably be better off with just a Timer control, avoiding the need to call Invoke or BeginInvoke lots of times. 如果BackgroundWorker 主要是在与UI进行对话,则最好使用Timer控件更好,而不必多次调用InvokeBeginInvoke

However, generally I would prefer a more "observer" based design here, with change-notification events (either FooChanged or INotifyPropertyChanged ) and event-handlers that cause the UI to reflect changes. 但是, 通常,我更喜欢这里的基于“观察者”的设计,其中包含更改通知事件( FooChangedINotifyPropertyChanged )和事件处理程序,这些事件处理程序会导致UI反映更改。

您需要计时器控制而不是后台工作人员

The exception you're receiving would be the result of calling Update() (which is modifying one or more forms in your primary thread ) directly from _DoWork within your BackgroundWorker's thread. 您收到的异常是直接从BackgroundWorker线程中的_DoWork调用Update() (正在修改主线程中的一个或多个表单)的结果。

If you're going to use the BackgroundWorker method: 如果要使用BackgroundWorker方法:

  • Set your worker's .WorkerReportsProgress property to true 将工作人员的.WorkerReportsProgress属性设置为true
  • When you perform your loop, use the worker's .ReportProgress() method to trigger the worker's _ProgressChanged event handler. 执行循环时,请使用工作程序的.ReportProgress()方法来触发工作程序的_ProgressChanged事件处理程序。
  • The _ProgressChanged event handler can then perform a call to your form's Update() method safely 然后, _ProgressChanged事件处理程序可以安全地调用表单的Update()方法。

If you move away from using the worker (especially if your background worker solely exists for this loop), then I'd suggest you go with Marc's suggestion of standard event handlers. 如果您不使用该工作程序(特别是如果您的后台工作程序仅用于此循环),那么我建议您接受Marc关于标准事件处理程序的建议 That route will yield less processor overhead (however minimal it currently may or may not be) than adding in your external loop or a Timer control. 与添加外部循环或Timer控件相比,该路由将产生更少的处理器开销(但是,当前可能有或没有)。

Either route should address the Cross-thread exception. 任一路由都应解决跨线程异常。

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

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