Как ждать, пока BackgroundWorker завершит работу другого BackgroundWorker (C#)?
Прежде всего, я все еще новичок, поэтому я был бы признателен, если бы у вас было немного терпения:)
Я сегодня так сильно чесал голову об этом.
Дело в том, что я хочу работать с тремя разными специалистами. Но я хотел бы подождать, пока один не закончит запуск следующего, и так далее.
Каждый фоновый работник требует времени, чтобы закончить. Короче говоря, дело в том, что я использую WaitOne(), поэтому всякий раз, когда предыдущий фоновый работник говорит мне, что он готов, я могу начинать запуск нового, но поток пользовательского интерфейса останавливается, пока три фоновых работника не закончат работу.
Я настраиваю другой AutoResetEvent, который заботится обо всем, что ждет и работает.
Вот код:
AutoResetEvent _resetRIEvent = new AutoResetEvent(false);
AutoResetEvent _resetHEvent = new AutoResetEvent(false);
AutoResetEvent _resetSEvent = new AutoResetEvent(false);
await Task.Run(() => bgwTestResInd.RunWorkerAsync());
_resetRIEvent.WaitOne();
await Task.Run(() => bgwTestHipot.RunWorkerAsync());
_resetHEvent.WaitOne();
await Task.Run(() => bgwTestSurge.RunWorkerAsync());
_resetSEvent.WaitOne();
MessageBox.Show("Im done for real.");
Кроме того, разрешено ли это делать?
private void bgwTestResInd_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_resetRIEvent.Set();
}
private void bgwTestHipot_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_resetHEvent.Set();
}
private void bgwTestSurge_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
_resetSEvent.Set();
}
2 ответа
Вместо того, чтобы создавать фоновых рабочих и затем использовать искусственные сочетания задач и примитивы синхронизации для запуска рабочих в разное время, просто используйте TPL от начала до конца, чтобы сделать все это:
await Task.Run(() => TheWorkThatTheFirstBGWWasDoing());
await Task.Run(() => TheWorkThatTheSecondBGWWasDoing());
await Task.Run(() => TheWorkThatTheThirdBGWWasDoing());
Или, если все операции связаны с работой процессора, вы можете просто использовать один вызов Task.Run
:
await Task.Run(() =>
{
TheWorkThatTheFirstBGWWasDoing());
TheWorkThatTheSecondBGWWasDoing());
TheWorkThatTheThirdBGWWasDoing());
});
Готово.
Если вы действительно должны использовать фонового работника (для которого нет веских причин, но в любом случае), тогда все, что вам нужно сделать, это позвонить RunWorkerAsync
в законченном обработчике BGW, который ему нужно ждать, или, что еще лучше, просто есть один BGW, который выполняет работу, выполняемую первым, затем выполняет работу, которую должен выполнять второй, затем выполняет работа, которую должен сделать третий.
Если вы все еще хотите придерживаться своего плана, вот код
class Program
{
static void Main(string[] args)
{
var test=new Test();
test.Run();
Console.ReadKey();
}
private class Test
{
AutoResetEvent _resetRIEvent = new AutoResetEvent(false);
AutoResetEvent _resetHEvent = new AutoResetEvent(false);
AutoResetEvent _resetSEvent = new AutoResetEvent(false);
private BackgroundWorker bgwTestResInd = new BackgroundWorker();
private BackgroundWorker bgwTestHipot=new BackgroundWorker();
private BackgroundWorker bgwTestSurge=new BackgroundWorker();
public async void Run()
{
bgwTestResInd.DoWork += BgwTestResInd_DoWork;
bgwTestHipot.DoWork += BgwTestHipot_DoWork;
bgwTestSurge.DoWork += BgwTestSurge_DoWork;
await Task.Run(() => bgwTestResInd.RunWorkerAsync());
_resetRIEvent.WaitOne();
await Task.Run(() => bgwTestHipot.RunWorkerAsync());
_resetHEvent.WaitOne();
await Task.Run(() => bgwTestSurge.RunWorkerAsync());
_resetSEvent.WaitOne();
Console.Write("Done");
}
private void BgwTestHipot_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("BgwTestHipot done..");
_resetHEvent.Set();
}
private void BgwTestSurge_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("BgwTestSurge done..");
_resetSEvent.Set();
}
private void BgwTestResInd_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("BgwTestResInd done..");
_resetRIEvent.Set();
}
}
}
Просто добавьте свой код в методы DoWork, и они будут выполняться в той последовательности, в которой вы сбрасываете свои AutoResetEvents