While working on the Listener and ensuring that it cleans itself up if there's an error, I went down a bit of a rabbit hole with hypotheticals and arrived at the realization that:
- I need to implement a
TryDispose() extension that swallows exceptions, for cases where a Dispose() needs to Dispose multiple other things; if one throws the others aren't disposed
- I should (but don't have to if I use
TryDispose() everywhere) go through all of my Dispose() implementations and ensure they are both idempotent and thread safe
Idempotentcy should be attempted in every implementation via a Disposed boolean that's set in the body of the Dispose() that does the work, but if any of those calls throw, it's not set, and if another thread enters the critical section before Disposed is set, everything will get called twice.
The impact of this, if it really is a problem, is at worst a resource leak, at next-worst stuff avoiding GC longer than it should, and at best not happening.
While working on the
Listenerand ensuring that it cleans itself up if there's an error, I went down a bit of a rabbit hole with hypotheticals and arrived at the realization that:TryDispose()extension that swallows exceptions, for cases where aDispose()needs toDisposemultiple other things; if one throws the others aren't disposedTryDispose()everywhere) go through all of myDispose()implementations and ensure they are both idempotent and thread safeIdempotentcy should be attempted in every implementation via a
Disposedboolean that's set in the body of theDispose()that does the work, but if any of those calls throw, it's not set, and if another thread enters the critical section beforeDisposedis set, everything will get called twice.The impact of this, if it really is a problem, is at worst a resource leak, at next-worst stuff avoiding GC longer than it should, and at best not happening.