Reputation: 7465
In my code, I have a class which create a new thread. This new thread has a Dispatcher, thus the thread will not finish unless I call
Dispatcher.CurrentDispatcher.InvokeShutdown();
The thread cannot be referenced outside of my class. So I was thinking : how to ensure that my thread finish when my object is garbage collected ?
One response is to use IDisposable, but if someone forget to call Dispose(), the thread will never stop so it's not a solution.
Another response is two use Dispose + Destructor, but I've heard that we should only use the destructor for release unmanaged resource. I'm in a dead end.
What is the best solution ?
Upvotes: 2
Views: 501
Reputation: 4425
There's a lot of useful information on dispose and finalize here. Obviously if you're writing a reusable class or a library to be used by other programmers, you can't assume that the Dispose method will always be called, and so it would be wise to implement a finalizer:
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
}
~MyClass() {
Dispose (false);
}
It seems like this is not that reusable a class you're writing, and is used pretty much within your own program. In that case, you have the following choices:
Dispose
isn't calledYou can guard the last 2 from being compiled in to the release by guarding them:
~MyClass() {
Dispose (false);
#if DEBUG
// log a warning or scream at the developer in some way
#endif
}
Upvotes: 1
Reputation: 10349
"Dispose + Destructor" solution seems fine to me. You could employ some tricks, as Jon said, to detect whether a Dispose call was missed, but having the thread stopped on a finalizer call will be an additional safeguard.
By the way, a thread is an unmanaged resource.
Upvotes: 1
Reputation: 1500375
One option is to use a finalizer only for debug builds. Don't make it just "nicely" shut down the thread: make it log a warning very prominently. That should help you to isolate places where you've forgotten to dispose of the object properly.
However, it's not foolproof and it has the undesirable property of making the debug and release code different.
Would your dispatcher normally receive events very frequently? Could you make it at least log a warning if it's received no events for a long time?
One fairly nasty option would be to make the dispatcher have a weak reference to the disposable object. It could periodically check whether the object has been garbage collected (using WeakReference.IsAlive
) and shut itself down if so. Again, that's not terribly pleasant (and should log a warning).
Upvotes: 2