Did you wish the BackgroundWorker had a generic method?

We all love Generics. I love a little too much. It just makes me feel clean and tidy whenever I use it in my code. Awesome. Ok, enough of my incest for Generics.

It is quite common thing in a Windows desktop client application to have a user interface, which in response to some user actions performs certain tasks in the background. You certain would not want to make things like database/webservice calls on the UI thread. This could end up in showing the nice “Not Responding” message in your application title bar. If it is Vista you are running, it might be the Blue Screen of death who knows. In a normal Windows Forms application you would spawn a background thread and perform the tasks there. In a WPF application, well you could do the same but there is a BackgroundWorker available that does it for you. A straightforward usage of this class can be as below,

var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += BackgroundWorkerDoWork;
backgroundWorker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted;
backgroundWorker.RunWorkerAsync();


The problem is, say you have 10 buttons on your UI and you want to make 10 different webservice calls one for each button click event. You would end up with 10 different BackgroundWorker objects each with their handlers scattered in some class. I think it can be made a little tidier, you would require 10 different BackgroundWorker objects for sure, but a Generic wrapper around this could make life a little easier. We can do this by using a generic class and a generic delegate in it. Enough words, lets see some code,



internal class ServiceHelper<T>
where T: class
{
private readonly BackgroundWorker backgroundWorker;
internal delegate void Completed(T result);
internal event Completed CompletedHandler;

internal ServiceHelper()
{
backgroundWorker = new BackgroundWorker();
}

internal void InvokeMethod(Func<T> method)
{
backgroundWorker.DoWork += BackgroundWorkerDoWork;
backgroundWorker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted;
backgroundWorker.RunWorkerAsync();
}

private void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e == null)
return;
var result = e.Result as T;
if (result == null)
throw new InvalidCastException("The result obtained is not of the requested type.");
if (CompletedHandler != null)
CompletedHandler(result);
}

private void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
if (e == null)
return;
var method = e.Argument as Func<T>;
if (method == null)
return;
e.Result = method();
}
}


All we have done is wrapped the BackgroundWorker inside a generic class and provided a generic event handler for clients to subscribe to.



Happy Programming!

Abhang Rane