C # я должен создать один фоновый работник или много? - PullRequest
24 голосов
/ 13 сентября 2011

Я один из тех случайных программистов, поэтому у меня не так много знаний о наилучшей практике программирования.

У меня есть приложение, которое в настоящее время использует 4 Background Worker.

Итак, я объявляю их:

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

Затем настройте их:

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);

И затем я использую bw1.RunWorkerAsync (), bw2.RunWorkerAsync () и т. Д. ...

Дело в том, что я никогда не звоню им одновременно, они звонят в разные точки довольно линейно.

Итак, мой вопрос: лучше ли иметь много «предварительно сконфигурированных» фоновых рабочих или иметь одного и изменять события DoWork и RunWorkerCompleted в соответствии с тем, что я хочу, чтобы они делали?

Ответы [ 5 ]

27 голосов
/ 13 сентября 2011

Обычно я использую фоновых работников совсем по другому шаблону.Вместо того, чтобы определять их сразу в начале, включая соответствующие обработчики событий, я создаю их на лету, когда я делаю то, что им нужно.

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();
}

Что-то в этом роде.Преимущество состоит в том, что у вас есть весь код, выполняющий что-либо с или в фоновом режиме в одном месте, а также примерно в правильном порядке.

23 голосов
/ 13 сентября 2011

С архитектурной точки зрения лучше иметь отдельного фонового работника для каждой фоновой задачи, который логически не связан с другими задачами класса.

5 голосов
/ 13 сентября 2011

Обычно целесообразно использовать несколько потоков, если это помогает более эффективно использовать ресурсы в вашей системе.Для задач, интенсивно использующих процессор, хорошей отправной точкой является один поток на ядро ​​процессора.Для задач с интенсивным вводом-выводом у вас может быть гораздо больше.

Если у вас есть возможность использовать .NET 4, я бы обратился к параллельной библиотеке задач вместо BackgroundWorker.По умолчанию он примет относительно разумные решения о том, сколько потоков одновременно выполнять, в дополнение к более простой модели программирования.

0 голосов
/ 13 сентября 2011

Вы запускаете рабочих для каких-то вычислительных целей.Если расчет одного вызова используется или каким-либо образом зависит от другого, вы можете использовать более одного работника для достижения лучшей производительности (кстати, это слишком предмет для измерения).Если вам просто нужно выполнить 4 задания и запустить их в отдельном потоке, чтобы не блокировать основной пользовательский интерфейс, один из них - довольно хорошее решение.

0 голосов
/ 13 сентября 2011

Выполнение обработки с использованием BackgroundWorker означает, что вы делаете это в отдельном потоке. Поэтому, если вам не нужна многопоточность, вам не нужны отдельные фоновые работники. Если вы дождетесь завершения после того, как приступите к работе каждого из ваших работников, у вас может быть только один работник. Это также может удалить некоторые дубликаты кода ...

...