I've been reading up on .NET Threading and was working on some code that uses a ManualResetEvent. I have found lots of code samples on the internet. However, when reading the documentation for WaitHandle, I saw the following:
WaitHandle implements the Dispose pattern. See Implementing Finalize and Dispose to Clean Up Unmanaged Resources.
None of the samples seem to call .Close() on the ManualResetEvent objects they create, even the nice Recursion and Concurrency article from the pfxteam blog (Edit - this has a using block I has missed). Is this just example oversight, or not needed? I am curious because a WaitHandle "encapsulates operating system–specific objects," so there could easily be a resource leak.
I've used
ManualResetEvent
a lot and don't think I've ever used it inside a single method--it's always an instance field of a class. Thereforeusing()
often does not apply.If you have a class instance field that is an instance of
ManualResetEvent
, make your class implementIDisposable
and in yourDispose()
method callManualResetEvent.Close()
. Then in all usages of your class, you need to useusing()
or make the containing class implementIDisposable
and repeat, and repeat...You'll notice the code
uses the 'using' keyword. This automatically calls the dispose method when finished even if the code throws an exception.
In general, if an object implements
IDisposable
it is doing so for a reason and you should callDispose
(orClose
, as the case may be). In the example you site, the ManualResetEvent is wrapped inside ausing
statement, which will "automatically" handle callingDispose
. In this case,Close
is synonymous withDispose
(which is true in mostIDisposable
implementations that provide aClose
method).The code from the example:
expands to
I was recently forwarded an excerpt from C# 4.0 in a Nutshell: The Definitive Reference By Joseph Albahari, Ben Albahari. On page 834, in Chapter 21: Threading there is a section talking about this.
If you're using a
ManualResetEvent
with anonymous methods then it's obviously useful. But as Sam mentioned they can often be passed around into workers, and then set and closed.So I would say it depends on the context of how you are using it - the MSDN WaitHandle.WaitAll() code sample has a good example of what I mean.
Here's an example based on the MSDN sample of how creating the WaitHandles with a
using
statement would exception:The Close is handled inside ManualResetEvent's Dispose, and that's called by the 'using' statement.
http://msdn.microsoft.com/en-us/library/yh598w02%28VS.100%29.aspx