I have an object that has a BackgroundWorker
thread (purely a queue of Action delegates). i.e., it's the common, simple single-producer single-consumer scenario.
When the single producer is collected, I would like it to enqueue a Terminate action to the BackgroundWorker
thread.
It almost sounds easy - use a finalizer - but that breaks the "don't touch a managed resource in a finalizer" rule.
So how do I ensure the thread terminates cleanly once it has no more work to do?
Answers I'd rather not take:
IDisposable
: This would require a massive breaking change to the base class, but I accept it is perhaps required (this always seems to be a problem with the IDisposable pattern..)ThreadPool
: These are long running actions that must be run in order. So I would consider a dedicated thread to be the logical choice.WeakReference
: I just thought of this one. Perhaps it is the correct way to do this (?). Basically the Thread keeps a WeakReference
back to the owning object, and periodically wakes itself to check if that WeakReference
is still alive, when it dies it enqueues a Terminate. Not exactly elegant - I don't like the "periodically wakes itself" bit - but is this the best solution?IDisposable
or something similar sounds like the best approach to me - explicitly say when you've finished producing, rather than triggering that from garbage collection.
Fundamentally it sounds like the problem isn't terminating the worker thread - it's indicating that you've finished producing. I do understand that that can be tricky in some situations, but if at all possible it'll make your life more predictable if you can do that explicitly.