线程都共享资源。这就是多线程操作的全部问题。
MSDN说:
You must be careful not to manipulate any user-interface objects in your DoWork event >handler. Instead, communicate to the user interface through the ProgressChanged and RunWorkerCompleted events.
BackgroundWorker events are not marshaled across AppDomain boundaries. Do not use a BackgroundWorker component to perform multithreaded operations in more than one AppDomain.
然而,当我使用 backgroundworker 时,并不是我需要小心不要操作任何 UI 对象,而是如果我尝试从 DOWork 事件访问 UI 组件,那是不能的。代码可以编译,但是当 DoWork 的代码运行时,出现错误:
Cross-thread operation not valid: Control 'utAlerts' accessed from a thread other than the thread it was created on.
MSDN 没有说明这是如何完成的或为什么这样做。后台 worker 是否装饰有一些阻止这种情况的属性?这是如何实现的?
最佳答案
如果您的处理程序是 UI 类中的实例方法,则您应该有权访问该类的成员。
it's that my app won't even compile if I try to access the UI components from the DOWork event.
只有当您的 DoWork
处理程序是静态的或位于与 UI 组件不同的类中时,才会发生这种情况。在这种情况下,您可能无法访问它们,因为它们对您不可见。
编辑:
BackgroundWorker 旨在执行与您的用户界面无关的“工作”。您不能在 UI 线程以外的任何线程上更改用户界面元素,因为用户界面元素往往具有线程关联性。这实际上与 BackgroundWorker 无关,而与线程和用户界面元素有关。
BW 旨在通过为您提供自动编码回 UI 线程的进度和完成事件来解决此问题,从而允许您在那里更改 UI 元素。但是,您始终可以通过 Windows 窗体中的 Control.Invoke
或 WPF 中的 Dispatcher.Invoke
自己直接执行此操作。
至于它是如何工作的——这取决于你使用的是什么框架。例如,在 Windows 窗体中,每个 Control
(它是所有 UI 元素的基类)都有一个 Handle,并且该 Handle 在内部是一个 native 窗口句柄。此句柄用于 check the window's Thread ID针对当前线程 ID。这允许在不存储额外变量的情况下进行检查。
关于c# - 为什么不能从 backgroundworker 访问 UI 组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5599164/