Avoiding code duplication for similar backgroundworkers used in dissimilar classes

I have several classes that are all using backgroundWorker threads to run logic while updating a status bar on my main form.

I'm finding that a lot of the set up and reporting code for the backgroundWorkers is the same in multiple classes, e.g.:

BackgroundWorker wkrBackground = new BackgroundWorker();
wkrBackground.WorkerReportsProgress = true;
wkrBackground.WorkerSupportsCancellation = true;
wkrBackground.RunWorkerCompleted += new RunWorkerCompletedEventHandler(wkrBackground_RunWorkerCompleted);
wkrBackground.ProgressChanged += new ProgressChangedEventHandler(wkrBackground_ProgressChanged);

I'm sure that I will not need to use backgroundWorkers in any other ways than this, so would like to avoid the duplication.

I have considered the following options:

  • Making all the classes that use the background worker inherit from the same abstract class so that I can put the worker creation method in that, as well as the wkrBackground_RunWorkerCompleted and wkrBackground_ProgressChanged
  • Extending backgroundWorker to give it a new constructor that sets WorkerReportsProgress and WorkerSupportsCancellation and using that class instead
  • Creating a worker utility class with a createBackgroundWorker method (though these last two options would not avoid the duplication of the final two lines as the specifics of those methods would still be included in the original classes).

I'm wondering if there is a standard way to deal with this kind of duplication?

Jon Skeet
people
quotationmark

The final option seems reasonable to me - and you can avoid the duplication of the final two lines, and even the one that you missed (the DoWork event):

public static BackgroundWorker CreateBackgroundWorker
    (DoWorkEventHandler workHandler,
     ProgressChangedEventHandler progressHandler,
     RunWorkerCompletedEventHandler completedHandler)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.WorkerReportsProgress = true;
    worker.WorkerSupportsCancellation = true;
    worker.DoWork += workHandler;
    worker.ProgressChanged += progressHandler;
    worker.RunWorkerCompleted += completedHandler;
}

Then call that with (say):

BackgroundWorker = BackgroundWorkerHelper.CreateBackgroundWorker(
    wkrBackground_DoWork, wkrBackground_ProgressChanged,
    wkrBackground_RunWorkerCompleted);

Alternatively, having an interface with a method for each of the DoWork, ProgressChanged and RunWorkerCompleted events would be pretty sweet too, as per Matthew's suggestion... although it makes those three methods effectively public when they can otherwise be private. It might help with testing, mind you...

people

See more on this question at Stackoverflow