Home
Atom Feed

Inline BackgroundWorker

In one of my recent projects, I wanted to spin off all database write calls in separate threads to increase UI performance and response. The simplest way to implement this is to use a BackgroundWorker. The MSDN code uses a BackgroundWorker that is defined in the class as a private variable, but since I needed an unspecified amount of workers this did not quite suit my application.

It's not a problem to create BackgroundWorkers inside a function, so my first take on the issue looked like this:

var worker = new BackgroundWorker();

worker.DoWork += (sender, args) =>
    {
        // Do work on separate thread.
        // NOTE: UI controls are not available here, store data in args.Result instead
    };
worker.RunWorkerCompleted += (sender, args) =>
        {
            // Worker completed
            // NOTE: We are now back on the UI thread, stored data is available in args.Result (Remember to cast to correct type).
        };

worker.RunWorkerAsync();

The above code works, but is not simple enough. I wanted to make an inline / one-line function so I made a BackgroundWorker wrapper class. The class uses an inverted Singleton principle to always spin off a new BackgroundWorker when it's used, and takes event handlers or delegates as function parameters:

/// <summary>
/// BackgroundWorker wrapper for running background workers inline.
/// </summary>
public class InlineBackgroundWorker
{
    /// <summary>
    /// The background worker instance
    /// </summary>
    private readonly BackgroundWorker backgroundWorker = new BackgroundWorker();

    /// <summary>
    /// Prevents a default instance of the <see cref="InlineBackgroundWorker"/> class from being created.
    /// </summary>
    private InlineBackgroundWorker()
    {
    }

    /// <summary>
    /// Generates a new instance of the <see cref="InlineBackgroundWorker"/> class.
    /// </summary>
    public static InlineBackgroundWorker NewInstance
    {
        get
        {
            return new InlineBackgroundWorker();
        }
    }

    /// <summary>
    /// Runs the BackgroundWorker with the specified event handlers.
    /// </summary>
    /// <param name="doWork">The DoWork event handler.</param>
    /// <param name="workerCompleted">The RunWorkerCompleted event handler.</param>
    /// <param name="progressChanged">The ProgressChanged event handler.</param>
    public void Run(DoWorkEventHandler doWork, RunWorkerCompletedEventHandler workerCompleted = null, ProgressChangedEventHandler progressChanged = null)
    {
        this.backgroundWorker.DoWork += doWork;

        if (workerCompleted != null) 
        { 
            this.backgroundWorker.RunWorkerCompleted += workerCompleted;
        }

        if (progressChanged != null)
        {
            this.backgroundWorker.ProgressChanged += progressChanged;
        }

        this.backgroundWorker.RunWorkerAsync();
    }
}

Here are some examples on how to use this class:

InlineBackgroundWorker.NewInstance.Run(
    (sender, args) =>
        {
            // Do work on separate thread.
            // NOTE: UI controls are not available here, store data in args.Result instead
        },
    (sender, args) =>
        {
            // Worker completed
            // NOTE: We are now back on the UI thread, stored data is available in args.Result (Remember to cast to correct type).
        });

InlineBackgroundWorker.NewInstance.Run(
    delegate
        {
            // Do work on separate thread.
            // NOTE: UI controls are not available here
        },
    delegate
        {
            // Worker completed
            // NOTE: We are now back on the UI thread.
        });

Much more elegant. :-)