我有一台ManualResetEvent。有一次,我使用WaitOne等待该事件。令我惊讶的是,我在WaitOne中收到了一个OnPaint事件。这种情况也经常发生。
堆栈跟踪如下所示:

我知道WaitOne会阻塞当前线程,并且在事件触发之前不允许执行任何其他代码。
有人能解释一下这里发生了什么吗?
发布于 2010-12-28 02:09:15
这是设计好的。CLR遵守单线程单元(STA)的合同。图形用户界面应用程序的主线程是STA正如Windows编程中所要求的,Main()方法上的STAThread属性确保。
STA线程的硬规则是它必须抽出一个消息循环(如Application.Run),并且永远不能阻塞。当后台线程使用任何COM单元线程对象时,阻塞STA线程极有可能导致死锁。它们有很多,剪贴板和WebBrowser是你在.NET程序中会遇到的常见工具。还有许多不太显眼的,可以作为.NET包装器类使用。
当您使用LOCK语句或调用同步类的Wait方法时,CLR通过执行消息循环来确保阻塞不会导致死锁。或Thread.Join()。该消息循环调度WM_PAINT消息,导致Paint事件运行。
您需要重新构建您的程序,以确保这不会造成问题。非常重要的是要专注于根本不阻塞主线程。当您有BackgroundWorker类或Control.BeginInvoke()可供使用时,很少需要它。出于某种奇怪的原因,Mutex类不做这种抽运,这可能是另一种方式。尽管如果你这样做,死锁就会潜伏在角落里。
发布于 2010-12-28 01:05:46
我在lock()语句中也看到了这种行为。显然,.net框架线程类在等待UI线程上的锁时会启动一个消息循环。这只是解释了正在发生的事情。原因可能是为了防止在使用旧的STA COM对象时出现死锁。我不知道有什么方法可以防止这种情况发生。
https://stackoverflow.com/questions/4540244
复制相似问题