没有“交叉线程”,我可以从BackgroundWorker访问什么?

时间:2009-02-14 10:05:15

标签: windows backgroundworker multithreading

我意识到我无法从BackgroundWorker的DoWork事件处理程序访问Form控件。 (如果我尝试,我会得到一个异常,如预期的那样)。

但是,我是否可以访问我的表单上存在的其他(自定义)对象?

例如,我创建了一个“设置”类并在我的表单中实例化它,我似乎能够读取和写入其属性。

这只是运气吗?

如果我有静态课怎么办?我可以安全地访问它吗?

4 个答案:

答案 0 :(得分:4)

@Engram:

你有它的要点--CrossThreadCalls只是MS放入.NET Framework的一个很好的功能,以防止“骨头”类型的并行编程错误。它可以被覆盖,因为我猜你已经发现了,通过在上设置“AllowCrossThreadCalls”属性(而不是在类的实例上,例如设置Label.AllowCrossThreadCalls和不是lblMyLabel.AllowCrossThreadCalls)。

但更重要的是,你是否需要使用某种锁定机制。每当你有多个执行线程(无论是线程,进程还是其他)时,你需要确保当你有一个线程读/写一个变量时,你可能不希望其他一些线程插入并改变该值下的值。第一线的脚。

.NET Framework实际上提供了一些其他机制,这些机制可能比锁定代码更有用,具体取决于具体情况。第一种是使用Monitor类,它具有锁定特定对象的效果。当您使用它时,其他线程可以继续执行,只要它们不尝试锁定同一个对象。另一个非常有用和常见的并行编程思想是Mutex(或Semaphore)。 Mutex基本上就像是一个在线程之间捕获旗帜的游戏。如果一个线程抓取该标志,则在第一个线程丢弃之前,没有其他线程可以抓取它。 (信号量就像一个互斥体,除了游戏中可以有多个标志。)

显然,这些概念都不适用于所有特定问题 - 但是有一些工具可以帮助你,有朝一日可能会派上用场:)

答案 1 :(得分:1)

您应该通过ProgressChangedRunWorkerCompleted事件(而不是您所记录的DoWork()方法)与用户界面进行通信。

原则上,您可以调用IsInvokeRequired,但BackgroundWorker类的设计者创建了ProgressChanged回调事件,以便更新UI元素。

[注意:BackgroundWorker事件不是跨AppDomain边界编组的。不要使用BackgroundWorker组件在多个AppDomain中执行多线程操作。]

MSDN Ref

答案 2 :(得分:1)

好的,我已经对此做了一些研究,我认为有一个答案。 (让投票决定我是否正确!)

答案是..您可以访问范围内的任何自定义对象,但是您的访问权限不是线程安全的。

为了确保它是线程安全的,您应该使用lock。 lock关键字阻止执行特定代码段的多个线程。 (实际上正确使用它!)

当您尝试访问Control时发生的交叉线程异常是专为控件设计的安全机制。 (让用户进行线程安全调用更容易也可能更有效,然后将控件本身设计为线程安全的。)

答案 3 :(得分:-1)

您无法访问从另一个线程在一个线程中创建的控件。 您可以使用您提到的Settings类,也可以使用InvokeRequired属性和Invoke控制方法。

我建议您查看这些页面上的示例:

http://msdn.microsoft.com/en-us/library/ms171728.aspx

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx