Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# should I create one Background worker or many?

I am one of those accidental programmer so I don't have that much knowledge regarding programming best practice.

I have an application that currently uses 4 Background Worker.

So I declare them:

private BackgroundWorker bw1;
private BackgroundWorker bw2;
private BackgroundWorker bw3;
private BackgroundWorker bw4;

Then configure them:

bw1 = new BackgroundWorker();
bw1.WorkerReportsProgress = true;
bw1.DoWork += new DoWorkEventHandler(bw1_DoWork);
bw1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw1_RunWorkerCompleted);
bw1.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

bw2 = new BackgroundWorker();
bw2.WorkerReportsProgress = true;
bw2.DoWork += new DoWorkEventHandler(bw2_DoWork);
bw2.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw2_RunWorkerCompleted);
bw2.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

bw3 = new BackgroundWorker();
bw3.WorkerReportsProgress = true;
bw3.DoWork += new DoWorkEventHandler(bw3_DoWork);
bw3.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw3_RunWorkerCompleted);
bw3.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

bw4 = new BackgroundWorker();
bw4.WorkerReportsProgress = true;
bw4.DoWork += new DoWorkEventHandler(bw4_DoWork);
bw4.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw4_RunWorkerCompleted);
bw4.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);

And then I use the bw1.RunWorkerAsync(), bw2.RunWorkerAsync(), and so on...

The thing is I never call them simultaneously, they are call at different point in a pretty linear way.

So my question is, is it better to have many "pre-configured" background workers or to have one and change the DoWork and RunWorkerCompleted events according to what I want it to do?

like image 690
Alex Avatar asked Sep 13 '11 18:09

Alex


3 Answers

Usually I use background workers in a quite different pattern. Instead of defining them all at once in the beginning including their respective event handlers, I create them on the fly when I do something that needs them.

public void SomeEventHandlerMaybe(object sender, EventArgs e) {
  // do something

  var bw = new BackgroundWorker();
  bw.ReportsProgress = true;
  bw.DoWork += delegate {
    // do work. You can use locals from here
  };
  bw.ProgressChanged += delegate { ... };
  bw.RunWorkerCompleted += delegate {
    // do something with the results.
  };
  bw.RunWorkerAsync();
}

Something like that. It has the benefit that you have all code that does something with or in the background worker in one place and roughly in the right order as well.

like image 176
Joey Avatar answered Oct 15 '22 09:10

Joey


From an architectural point of view, it is best to have a separate background worker for each background task, that is logically unrelated to another tasks of the class.

like image 24
Maxim V. Pavlov Avatar answered Oct 15 '22 08:10

Maxim V. Pavlov


Generally it's reasonable to use multiple threads if it helps with more efficient resource usage on your system. For CPU intensive tasks, one thread per CPU core is a good starting point. For IO intensive tasks, you can certainly have many more than that.

If you have the flexibility to use .NET 4, I would look into the Task Parallel Library instead of BackgroundWorker. By default, it will make relatively smart decisions for you about how many threads to run concurrently in addition to providing an easier programming model.

like image 6
Eric J. Avatar answered Oct 15 '22 07:10

Eric J.