Is it well defined to create a BackgroundWorker object only referenced by a local variable?

Viewed 92

I'm new to C# and WPF. I took hours reading online docs and examples to review some code. The code subclasses System.Windows.Controls.Page and use BackgroundWorker to do background computing.

From what I learned, the desired way to create a BackgroundWorker object in this case, is to make it referenced by a class member variable.

E.g.,

public class MyPage: System.Windows.Controls.Page
{   
    // Or: backgroundWorker = new System.ComponentModel.BackgroundWorker()
    private System.ComponentModel.BackgroundWorker backgroundWorker;
    ..
}

But the code under review creates the object referenced by a local variable.

// Inside a class member function
if (someCondition)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.WorkerSupportsCancellation = true;
    worker.WorkerReportsProgress = true;
    worker.DoWork += new DoWorkEventHandler(DoWork1);
    worker.DoWork += new DoWorkEventHandler(DoWork2);
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
    worker.RunWorkerAsync(this.DataContext);
}

Is this well defined? Will the object be eligible for GC after worker is out of scope since it's the obvious sole reference to the object? Or the framework adds extra reference count(s) due to those asnyc function callbacks?

By "well-defined", I mean the worker object is guaranteed to stay in memory at least until all the callbacks (e.g., RunWorkerCompleted) are finished.

Thanks!

1 Answers

The BackgroundWorker won't be immediately eligible for garbage collection provided that you call the RunWorkerAsync() method. You can confirm this yourself using a WeakReference:

BackgroundWorker worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.WorkerReportsProgress = true;
worker.DoWork += new DoWorkEventHandler(DoWork1);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
worker.RunWorkerAsync();

WeakReference viewModelWeakReference = new WeakReference(worker);
worker = null;
GC.Collect();
GC.WaitForPendingFinalizers();
MessageBox.Show(viewModelWeakReference.IsAlive.ToString());

Even if you dispose it right after you have called RunWorkerAsync(), it will still hang around until it has finished.

Related