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.
The stack trace looks like this:
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?
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With