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

发布于 2024-10-02 18:45:10 字数 813 浏览 8 评论 0原文

出于某种原因,我传统上在 C# 中使用 BackgroundWorkers 时遇到很多麻烦;他们的概念似乎确实难住了我,所以我希望这是一个相当基本的问题,并且可以很容易地纠正......

我有两种使用 .NET 远程处理来回通信的表单。现在,更改 Form1 上的设置会导致 Form2 上的某些内容发生变化,效果很好。但是,现在我需要以另一种方式使同样的事情工作(更改 Form2 上的某些内容会导致 Form1 更新),并且我不能以同样的方式执行此操作(由于设计的限制,我不能让 Form2 发送更改)到表格 1)。现在,我尝试在 Form1 上使用 BackgroundWorker 来不断调用每个子控件(放置在 Form1 上)上的“Update()”方法。这些控件中的每一个都可以从 Form2 中获取其等效设置的当前状态并更新自身(这很有效;“Update()”方法已被视为在 Form1 的初始化中起作用)。

这就是我的问题出现的地方。我不确定如何让BackgroundWorker在每个表单上不断调用“Update()”,因此在我的“DoWork()”方法中,我有一个“while(true)”循环,并且在其中BackgroundWorker调用“Update”每个子控件的 ()' 方法,然后休眠很短的时间,然后重复。

通过这种方式,我收到“InvalidOperationException 未由用户代码处理”错误,并详细说明“跨线程操作无效:控制‘comboBox_BGColor’是从创建它的线程以外的线程访问的。”现在,我基本上知道这意味着什么,也明白为什么会发生,但是,我不确定该做什么不同,或者如何改变事情以使其按预期工作。有人对此或我使用BackgroundWorker 的方式有任何提示吗?非常感谢您提供任何信息并花时间阅读本文!

I traditionally have a lot of trouble with BackgroundWorkers in C# for some reason; 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. Right now, changing a setting on Form1 causes something to change on Form2 and that works great. 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). 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). 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).

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.

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." 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? Thanks a lot for any information and for taking the time to read this!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清风无影 2024-10-09 18:45:10

UI 控件具有线程关联性。除了 UI 线程之外,您不应该从任何线程触摸控件(用于读取写入)。如果 BackgroundWorker 主要与 UI 对话,那么您可能最好只使用 Timer 控件,从而避免调用调用或BeginInvoke

然而,通常我更喜欢这里更多基于“观察者”的设计,带有更改通知事件(FooChangedINotifyPropertyChanged)和事件-导致 UI 反映更改的处理程序。

UI controls have thread affinity. You shouldn't touch the controls (for read or write) from any thread except the UI thread. 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.

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.

ゝ杯具 2024-10-09 18:45:10

你需要定时器控制而不是后台工作者

you need timer control instead of Background worker

往事随风而去 2024-10-09 18:45:10

您收到的异常可能是直接从您的BackgroundWorker 线程内的_DoWork 调用Update()(它正在修改主线程中的一个或多个表单)的结果。

如果您要使用 BackgroundWorker 方法:

  • 将工作线程的 .WorkerReportsProgress 属性设置为 true
  • 当您执行在您的循环中,使用工作器的 .ReportProgress() 方法来触发工作器的 _ProgressChanged 事件处理程序。
  • _ProgressChanged 事件处理程序可以安全地执行对表单的 Update() 方法的调用

如果您不再使用工作程序(特别是如果您的后台工作程序仅针对此循环而存在, ),那么我建议您采用Marc的建议标准事件处理程序。与添加外部循环或 Timer 控件相比,该路线将产生更少的处理器开销(无论当前可能或可能不是最小的)。

任一途径都应解决跨线程异常。

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.

If you're going to use the BackgroundWorker method:

  • Set your worker's .WorkerReportsProgress property to true
  • When you perform your loop, use the worker's .ReportProgress() method to trigger the worker's _ProgressChanged event handler.
  • The _ProgressChanged event handler can then perform a call to your form's Update() method safely

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. 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.

Either route should address the Cross-thread exception.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文