A month (or so) ago I wrote about the nice addition of the BackgroundWorker in .NET 2.0. The BackgroundWorker class is a great asset for those of us writing distributed applications. Rather then locking up our UI every time we make a expensive web service call we can run the process on a background thread and allow our users to continue working within the UI.
Over the past month I’ve found myself using the BackgroundWorker fairly often. Being the good lazy programmer that I am this has led me to create a helper object which I’ve called the BackgroundRunner. My BackgroundRunner is nothing more then a utility class for helping me reduce the amount of code required when running processes using a BackgroundWorker.
The BackgroundRunner has several static “Run” methods for running asynchronous operations. The Run method accepts delegates as parameters and handles wiring up the delegates to the appropriate events on the BackgroundWorker class.
///
<summary>Run an asynchronous operation and process the results./// </summary>
/// <param name="doWork">The delegate that will perform the actual work.</param>
/// <param name="completedEvent">The delegate that will work with the result provided by the doWork operation.</param>
/// <param name="onError">An event handler to handle any errors that occur during the doWork operation.</param>
/// <param name="suppressErrors">A flag indicating if errors should be suppressed.</param>
private static void Run(DoWorkEventHandler doWork, RunWorkerCompletedEventHandler completedEvent,
EventHandler<DataEventArgs<Exception>> onError, bool suppressErrors) {
BackgroundWorker worker = new BackgroundWorker();
numberOfRunningProcesses++;
worker.DoWork += delegate(object o, DoWorkEventArgs workEvents) {
try {
doWork(o, workEvents);
}
catch (Exception exception) {
if (onError != null) {
onError(o, new DataEventArgs<Exception>(exception));
}
else if(!suppressErrors) {
throw;
}
}
};
if (completedEvent != null) {
worker.RunWorkerCompleted += delegate(object o, RunWorkerCompletedEventArgs workerCompleteEventArgs) {
completedEvent(o, workerCompleteEventArgs);
numberOfRunningProcesses--;
};
}
worker.RunWorkerAsync();
}
Into the Run method I pass the DoWorkEventHandler which is actually going to do the work, the RunWorkerCompletedEventHandler which is going to handle the results of the “work”, an event handler for handling any errors / exceptions that occur, as well as a boolean which determines if errors that occur should be suppressed or not. You can also see I’m incrementing and decrementing a numberOfRunningProcesses variable. The numberOfRunningProcesses variable is a static that can be used to determine if we have any processes currently running in the background. This can be helpful if you want to prevent users from exiting your application while a background process is still running.
Feel free to use this code at your own risk. If you have comments or suggestions on how it can and should be improved please let me know.
UPDATE: removed verbosity from delegate assignment as recommended by Wesner Moise