I need to ensure thread safety when disposing an IDisposable
resource. The resource is cached multiple times in memory. When entries are evicted from the cache we have a callback that calls Dispose()
.
Therefore if the resource is cached three times, we'll call Dispose()
three times.
Is it the responsibility of the IDisposable
resource to ensure thread safety or the caller?
Either
Dispose
must use synchronization to ensure the calls don't overlapDispose
in such a way that it can be safely called from multiple threadsBoth of these are completely valid solutions to the problem. Which one is better will depend a lot on your system.
All other things being equal I would opt for #2. I prefer to have my objects be self sufficient and require as little help as possible to successfully execute in the environment they are designed for. Making it thread safe reduces the knowledge the rest of the system needs to use it correctly
The answer depends on whether the objects you want to dispose adhere to the guidelines or not.
If they do some things get simpler, from IDisposable.Dispose:
So if calling Dispose multiple times has no effect other than the first time it's called you only have to ensure that you don't call them at the same time. And that should absolutely be the responsibility of the caller.
Stephen Cleary wrote an article on CodeProject about how to implement IDisposable and the possible problems which I find extremely helpful.
It is up to the caller to guarantee thread safety through
lock
primitive orMonitor
classIDisposable
has nothing to do with thread safety. It's just a signal that the object's instance is ready to be garbage collected.It is the responsibility of the class implementing the IDisposable interface to ensure that the method can be called multiple times without throwing exception.
http://msdn.microsoft.com/en-us/library/fs2xkftw(v=vs.110).aspx
After an object is disposed, calls that fail because the object is disposed can and likely should throw an ObjectDisposedException (to aid in future debugging). If it is important that external objects know whether or not an object is disposed before making calls (because the object is shared), then it is customary to add a public boolean property (IsDisposed/Disposed) that indicates the state of the object.
EDIT: To more clearly cast this answer to the phrasing of the question, the class implementing IDisposable should implementing thread-safety if it is expected the class will be used in a cross-threaded environment. The link I posted shows an example of this at the bottom of the page.