Question

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?

Was it helpful?

Solution

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

OTHER TIPS

I'd create a Controller class to hold the logic.

Firstly, you would have to identify the common logic between between the display classes and encapsulate it as a set of methods specified in an interface. For the sake of argument, let's call that interface ICommonUiMethods.

Then, you would write a controller class which had a constructor to which you passed a BackgroundWorker and an ICommonUiMethods.

Inside the controller's constructor, subscribe to the appropriate background worker events.

In the controller's implementation for the handlers for those events, call the appropriate methods of the ICommonUiMethods passed to the constructor.

Your first option depends on what are the responsibilities of your classes. Although I doubt that they represent a is a relationship. One of quite common guidelines is that in general you should avoid inheritance if you can.

I'd also advice against the second option - reasons the same as above.

Your third choice seems the best option - after all, it's exactly what you want: one standard place of creating a background worker. So a concept of a factory is exactly what you need. You can also provide or configure delegate callbacks this way, so there will be even less duplication (even the last two lines you've mentioned).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top