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. :-)