在没有“跨线程”的情况下,我可以从后台工作程序访问什么?

发布于 2024-07-13 20:04:09 字数 232 浏览 7 评论 0原文

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

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

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

这只是运气好而已吗?

如果我有一个静态类怎么办? 我能够安全地访问它吗?

I realise that I can't access Form controls from the DoWork event handler of a BackgroundWorker. (And if I try to, I get an Exception, as expected).

However, am I allowed to access other (custom) objects that exist on my Form?

For instance, I've created a "Settings" class and instantiated it in my Form and I seem to be able to read and write to its properties.

Is it just luck that this works?

What if I had a static class? Would I be able to access that safely?

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

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

发布评论

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

评论(4

梦里的微风 2024-07-20 20:04:09

@Engram:

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

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

.NET Framework 实际上提供了几种其他机制,根据具体情况,这些机制可能比锁定代码更有用。 第一种是使用 Monitor 类,该类具有锁定特定对象的效果。 当您使用它时,其他线程可以继续执行,只要它们不尝试锁定同一对象即可。 另一个非常有用且常见的并行编程思想是 互斥体(或信号量)。 互斥体基本上就像线程之间的“夺旗”游戏。 如果一个线程获取了该标志,则其他线程都无法获取它,直到第一个线程将其丢弃。 (信号量就像互斥体,只不过游戏中可以有多个标志。)

显然,这些概念都不适用于每个特定问题 - 但拥有更多工具来帮助您可能会派上用场有一天:)

@Engram:

You've got the gist of it - CrossThreadCalls are just a nice feature MS put into the .NET Framework to prevent the "bonehead" type of parallel programming mistakes. It can be overridden, as I'm guessing you've already found out, by setting the "AllowCrossThreadCalls" property on the class (and not on an instance of the class, e.g. set Label.AllowCrossThreadCalls and not lblMyLabel.AllowCrossThreadCalls).

But more importantly, you're right about the need to use some kind of locking mechanism. Whenever you have multiple threads of execution (be it threads, processes or whatever), you need to make sure that when you have one thread reading/writing to a variable, you probably don't want some other thread barging and changing that value under the feet of the first thread.

The .NET Framework actually provides several other mechanisms which might be more useful, depending on circumstances, than locking in code. The first is to use a Monitor class, which has the effect of locking a particular object. When you use this, other threads can continue to execute, as long as they don't try to lock that same object. Another very useful and common parallel-programming idea is the Mutex (or Semaphore). The Mutex is basically like a game of Capture the Flag between your threads. If one thread grabs the flag, no other threads can grab it until the first thread drops it. (A Semaphore is just like a Mutex, except that there can be more than one flag in a game.)

Obviously, none of these concepts will work in every particular problem - but having a few more tools to help you out might come in handy some day :)

作死小能手 2024-07-20 20:04:09

您应该通过 ProgressChangedRunWorkerCompleted 事件(而不是您已经注意到的 DoWork() 方法)与用户界面进行通信。

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

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

MSDN 参考

You should communicate to the user interface through the ProgressChanged and RunWorkerCompleted events (and never the DoWork() method as you have noted).

In principle, you could call IsInvokeRequired, but the designers of the BackgroundWorker class created the ProgressChanged callback event for the purpose of updating UI elements.

[Note: BackgroundWorker events are not marshaled across AppDomain boundaries. Do not use a BackgroundWorker component to perform multithreaded operations in more than one AppDomain.]

MSDN Ref.

不寐倦长更 2024-07-20 20:04:09

好吧,我对此做了更多研究,我想有了答案。 (让投票决定我是否正确!)

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

为了确保它是线程安全的,您可能应该使用 锁定。 lock 关键字可防止多个线程执行某一特定代码段。 (以实际正确使用为准!)

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

Ok, I've done some more research on this and I think have an answer. (Let the votes decide if I'm right!)

The answer is.. you can access any custom object that's in scope, however your access will not be thread-safe.

To ensure that it is thread-safe you should probably be using lock. The lock keyword prevents more than one thread executing a particular piece of code. (Subject to actually using it properly!)

The Cross Threading Exception that occurs when you try and access a Control is a safety mechanism designed especially for Controls. (It's easier and probably more efficient to get the user to make thread-safe calls then it is to design the controls themselves to be thread-safe).

还在原地等你 2024-07-20 20:04:09

您无法从另一个线程访问在一个线程中创建的控件。
您可以使用您提到的 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

You can't access controls that where created in one thread from another thread.
You can either use Settings class that you mentioned, or use InvokeRequired property and Invoke methods of control.

I suggest you look at the examples on those pages:

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

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

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