Как правильно ждать, пока BackgroundWorker завершит работу?
Соблюдайте следующий фрагмент кода:
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += OnAsyncOperationCompleted;
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
Теперь предположим, что я хочу подождать, покаbw
заканчивает работать Какой правильный способ сделать это?
Мое решение таково:
bool finished = false;
var handler = GetTheRightHandler();
var bw = new BackgroundWorker();
bw.RunWorkerCompleted += (sender, args) =>
{
OnAsyncOperationCompleted(sender, args);
finished = true;
});
bw.DoWork += OnDoWorkLoadChildren;
bw.RunWorkerAsync(handler);
int timeout = N;
while (!finished && timeout > 0)
{
Thread.Sleep(1000);
--timeout;
}
if (!finished)
{
throw new TimedoutException("bla bla bla");
}
Но мне это не нравится.
Я подумал о заменеfinished
флаг с событием синхронизации, установите его вRunWorkerCompleted
обработчик и блокировать его позже вместо выполнения цикла while-sleep.
Увы, это неправильно, потому что код может выполняться в контексте синхронизации WPF или WindowsForm, и в этом случае я бы заблокировал тот же поток, что иRunWorkerCompleted
работает обработчик, что явно не очень умный ход.
Я хотел бы знать о лучшем решении.
Благодарю.
РЕДАКТИРОВАТЬ:
Постскриптум
Пример кода специально создан для того, чтобы уточнить мой вопрос. Я прекрасно осведомлен о обратном вызове завершения, и все же я хочу знать, как ждать до завершения. Это мой вопрос.Я в курсеThread.Join
, Delegate.BeginInvoke
, ThreadPool.QueueUserWorkItem
и т.д ... Вопрос конкретно оBackgroundWorker
.РЕДАКТИРОВАТЬ 2:
Хорошо, я думаю, будет намного проще, если я объясню сценарий.
У меня есть метод модульного теста, который вызывает некоторый асинхронный код, который, в свою очередь, в конечном итоге включаетBackgroundWorker
к которому я могу передать обработчик завершения. Весь код мой, поэтому я могу изменить реализацию, если захочу. Я не собираюсь, однако, заменитьBackgroundWorker
потому что он автоматически использует правильный контекст синхронизации, так что когда код вызывается в потоке пользовательского интерфейса, обратный вызов завершения вызывается в том же потоке пользовательского интерфейса, что очень хорошо.
В любом случае, возможно, что метод модульного тестирования достигнет конца, прежде чем BW закончит свою работу, что не очень хорошо. Поэтому я хочу подождать, пока BW завершит свою работу, и хотел бы узнать, как лучше всего это сделать.
В нем есть больше частей, но общая картина более или менее такая, как я только что описал.