Ответ 1
С архитектурной точки зрения лучше всего иметь отдельный фоновый рабочий для каждой фоновой задачи, который логически не связан с другими задачами класса.
Я один из тех случайных программистов, поэтому у меня нет таких знаний о наилучшей практике программирования.
У меня есть приложение, в котором в настоящее время используется 4 справочника.
Поэтому я объявляю их:
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 в соответствии с тем, что я хочу сделать?
С архитектурной точки зрения лучше всего иметь отдельный фоновый рабочий для каждой фоновой задачи, который логически не связан с другими задачами класса.
Обычно я использую фоновых работников в совершенно разных шаблонах. Вместо того, чтобы определять их все сразу в начале, включая их соответствующие обработчики событий, я создаю их на лету, когда я делаю что-то, что им нужно.
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();
}
Что-то вроде этого. Это имеет то преимущество, что у вас есть весь код, который что-то делает с или в фоновом рабочем месте в одном месте и примерно в правильном порядке.
В целом разумно использовать несколько потоков, если это помогает с более эффективным использованием ресурсов в вашей системе. Для задач с интенсивным использованием процессора один поток на ядро процессора является хорошей отправной точкой. Для интенсивных задач ввода-вывода у вас может быть много чего большего.
Если у вас есть гибкость в использовании .NET 4, я бы рассмотрел "Библиотека задач" вместо BackgroundWorker. По умолчанию он будет принимать относительно разумные решения относительно того, сколько потоков будет выполняться одновременно в дополнение к упрощенной модели программирования.
Выполнение вашей обработки с использованием BackgroundWorker означает, что вы делаете это в отдельном потоке. Поэтому, если вам не нужна многопоточность, нет необходимости в отдельных персональных работниках. Если вы ожидаете завершения после того, как вы начнете работу с каждым из ваших сотрудников, вы можете иметь только одного работника. Он также может удалить часть дублирования кода...
Вы запускаете работников для некоторых вычислительных целей. Если расчет одного вызова используется или каким-либо образом зависит от другого, вы можете использовать более одного рабочего, чтобы добиться более высокой производительности (кстати, это тоже предмет измерения). Если вам просто нужно выполнить 4 задания и запустить их в отдельном потоке, чтобы не блокировать основной пользовательский интерфейс, один рабочий - довольно хорошее решение.