c# - 这怎么可能 : OnPaint processed while in WaitOne

标签 c# .net winforms events

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

堆栈跟踪看起来像这样:

alt text

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

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

最佳答案

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

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

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

您需要重构您的程序以确保这不会导致问题。专注于完全不阻塞主线程非常重要。当您有 BackgroundWorker 类或 Control.BeginInvoke() 供您使用时,很少需要它。出于某种奇怪的原因,Mutex 类不进行这种泵送,这可能是另一种方式。尽管如果您这样做,死锁就潜伏在拐角处。

关于c# - 这怎么可能 : OnPaint processed while in WaitOne,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4540244/

相关文章:

c# - 如何使用 WPF 绑定(bind)触发 DataGrid 中特定单元格的更新

.net - 每个 DocumentStore 的 WaitForNonStaleResults

c# - 如何阻止自定义 ThrowHelper 出现在您的 StackTrace 中?

wpf - WPF和Windows Form是否有一些类似于div的控件行为

c# - 关于 Windows 事件的问题

c# - 如何声明具有数据成员字典类型的匿名类?

c# - 屏幕截图中未捕获对话框和菜单更改

java - Java 是否具有与 C# 的元组等效的变量类型?

c# - 在 winforms 中获取 ISP 提供商名称?

c# - 有问题的 if 语句