C#: Do I need to dispose a BackgroundWorker created at runtime?

RickL picture RickL · Nov 18, 2009 · Viewed 20.7k times · Source

I typically have code like this on a form:

    private void PerformLongRunningOperation()
    {
        BackgroundWorker worker = new BackgroundWorker();

        worker.DoWork += delegate
        {
            // perform long running operation here
        };

        worker.RunWorkerAsync();
    }

This means that I don't dispose the BackgroundWorker, whereas if I had added it by the form designer then I think it would get disposed.

Will this cause any problems? Is it more correct to declare a module-level _saveWorker, and then call Dispose on it from the form's dispose method?

Answer

Simon P Stevens picture Simon P Stevens · Nov 18, 2009

Yes, you should dispose of the background worker.

You may find it easier to use ThreadPool.QueueUserWorkItem(...) which doesn't require any clean up afterwards.


Additional detail on why you should always call Dispose():

Although if you look in the BackgroundWorker class it doesn't actually do any thread clean up in it's dispose method, it is still important to call Dispose because of the effect the class has on the garbage collector.

Classes with finalizers are not GCed immediately. They are kept and added to the finalizer queue. The finalizer thread then runs, (which following the standard pattern calls dispose). This means the object will survive into GC generation 1. And gen 1 collections are far rarer than gen 0 collections, so you object sticks around in memory for much longer.

If however you call Dispose(), the object will not be added to the finalization queue, so is free to be garbage collected.

It's not really big problem, but if you are creating a lot of them you'll end up using more memory than necessary. It should really be considered good practise to always call dispose on objects that have a dispose method.

So I suppose, all in all, it's not a 100% hard and fast requirement. Your app won't explode (or even leak memory) if you don't call Dispose(), but in some circumstances it may have negative effects. The background worker was designed for use from as a WinForms component so use it that way, if you have different requirements and don't want to use it as a WinForms component, don't use it, use the correct tool for the job, like the ThreadPool.