Search code examples
c#multithreadinggarbage-collectionfinalizer

How do I terminate a worker thread when the owning object is collected?


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?

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.