We were surprised to learn today that threads waiting on ManualResetEvent continue to wait for an event even after it closes. We expected the Close() call to implicitly signal pending threads.
We tracked this because some of our Windows services did not close as quickly as we would like. We change all of our Dispose implementations, which first close the ManualResetEvent links to call Set .
Can someone explain why Close does not indirectly call Set ? When do you want the waiting thread to keep waiting?
Here is our test code to demonstrate our results:
private static readonly Stopwatch _timer = Stopwatch.StartNew(); public static void Test() { var sync = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem(state => { Log("ThreadPool enter, waiting 250ms..."); sync.WaitOne(250); Log("ThreadPool exit"); }); Log("Main sleeping 100"); Thread.Sleep(100); Log("Main about to close");
When we run this code with the comment Set , we get this.
0 Main sleeping 100 0 ThreadPool enter, waiting 250ms... 103 Main about to close 103 Main waiting for exit 500ms 259 ThreadPool exit
When we explicitly call Set , we get this.
0 Main sleeping 100 0 ThreadPool enter, waiting 250ms... 98 Main about to close 98 ThreadPool exit 98 Main waiting for exit 500ms
Samuel neff
source share