这怎么可能:在WaitOne中处理OnPaint

Pie*_*kel 19 .net c# events winforms

我有一个ManualResetEvent.有一次,我等着那个事件WaitOne.令我惊讶的是,我OnPaint在演出期间收到了一个活动WaitOne.这种情况经常发生.

堆栈跟踪如下所示:

替代文字

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

有人可以解释这里发生了什么吗

Han*_*ant 22

这是设计的.CLR尊重单线程公寓(STA)的合同.GUI应用程序的主要线程是Windows编程中需要的STA,Main()方法上的[STAThread]属性确保了这一点.

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

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

您需要重新构建程序以确保这不会导致问题.非常重要的是根本不要阻止主线程.当您拥有BackgroundWorker类或Control.BeginInvoke()时,很少需要它.由于某些奇怪的原因,Mutex类不会进行这种抽运,这可能是另一种方式.虽然如果你这样做,僵局就会潜伏在拐角处.