这怎么可能:OnPaint 在 WaitOne 中处理 [英] How is this possible: OnPaint processed while in WaitOne

查看:28
本文介绍了这怎么可能:OnPaint 在 WaitOne 中处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ManualResetEvent.有一次,我使用 WaitOne 等待该事件.令我惊讶的是,我在 WaitOne 中收到了一个 OnPaint 事件.这种情况也经常发生.

I have a ManualResetEvent. At one point, I wait on that event using WaitOne. To my amazement, I received an OnPaint event while in the WaitOne. This happens quite often too.

堆栈跟踪如下所示:

我知道 WaitOne 会阻塞当前线程,并且在事件触发之前不允许执行任何其他代码.

I understood that a WaitOne would block the current thread and would not allow any other code to be executed until the event fires.

有人能解释一下这里发生了什么吗?

Could someone explain what happens here?

推荐答案

这是设计使然.CLR 遵守单线程单元 (STA) 的合同.GUI 应用程序的主线程是 Windows 编程中所要求的 STA,Main() 方法上的 [STAThread] 属性确保了这一点.

This is by design. The CLR honors the contract of a single-threaded apartment (STA). The main thread of a GUI app is STA as is required in Windows programming, the [STAThread] attribute on the Main() method ensures that.

STA 线程的硬性规则是它必须泵送一个消息循环(如 Application.Run)并且永远不能阻塞.当后台线程使用任何 COM 单元线程对象时,阻塞 STA 线程很可能会导致死锁.其中有很多,剪贴板和 WebBrowser 是您在 .NET 程序中会遇到的常见工具.还有许多不太明显的,可作为 .NET 包装器类使用.

Hard rules for an STA thread are that it must pump a message loop (like Application.Run) and can never block. Blocking an STA thread is highly likely to cause deadlock when background threads use any COM apartment threaded objects. There are many of them, the clipboard and WebBrowser are common ones you'll encounter in a .NET program. Many less visible ones as well, available as .NET wrapper classes.

当您使用 lock 语句或调用同步类的 Wait 方法时,CLR 通过泵送消息循环来确保阻塞不会导致死锁.或 Thread.Join().该消息循环调度 WM_PAINT 消息,导致 Paint 事件运行.

The CLR ensures blocking can't cause deadlock by pumping a message loop when you use the lock statement or call the Wait method of the synchronization classes. Or Thread.Join(). That message loop dispatches the WM_PAINT message, causing the Paint event to run.

您需要重构您的程序以确保这不会导致问题.专注于根本不阻塞主线程非常重要.例如,当您可以使用 BackgroundWorker 类或 Control.BeginInvoke() 时,很少需要它.由于某种奇怪的原因,互斥类不进行这种抽水,这可能是另一种方式.尽管如果你这样做,僵局就在附近.

You need to restructure your program to ensure this doesn't cause a problem. Pretty important to focus on not blocking the main thread at all. It is very rarely needed when you have, say, the BackgroundWorker class or Control.BeginInvoke() at your disposal. For some kind of odd reason the Mutex class doesn't do this kind of pumping, that could be another way. Although deadlock is lurking around the corner if you do.

这篇关于这怎么可能:OnPaint 在 WaitOne 中处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆