Соблюдайте следующий фрагмент кода:
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
, что явно не очень умное движение.
Я хотел бы узнать о лучшем решении.
Спасибо.
EDIT:
P.S.
- Образец кода настолько умышленно проясняет мой вопрос. Я прекрасно понимаю обратный вызов завершения и все же хочу знать, как подождать до завершения. Это мой вопрос.
- Я знаю
Thread.Join
,Delegate.BeginInvoke
,ThreadPool.QueueUserWorkItem
и т.д. Вопрос конкретно оBackgroundWorker
.
ИЗМЕНИТЬ 2:
ОК, я думаю, это будет намного проще, если я объясню сценарий.
У меня есть метод unit test, который вызывает некоторый асинхронный код, который, в свою очередь, в конечном итоге включает BackgroundWorker
, с которым я могу передать обработчик завершения. Весь код мой, поэтому я могу изменить реализацию, если захочу.
Однако я не собираюсь заменять BackgroundWorker
, потому что он автоматически использует правильный контекст синхронизации, так что, когда код вызывается в потоке пользовательского интерфейса, обратный вызов завершения вызывается в одном и том же потоке пользовательского интерфейса, что очень хорошо.
Во всяком случае, возможно, что метод unit test заканчивается до того, как BW завершит свою работу, что не очень хорошо. Поэтому я хочу подождать, пока BW не завершится, и хотел бы знать лучший способ для этого.
В нем больше штук, но общая картина более или менее похожа на то, что я только что описал.