Ожидание BackgroundWorker RunWorkerCompleted - PullRequest
2 голосов
/ 07 мая 2011

В основной теме у меня есть Timer. В событии Tick я запускаю BackgroundWorker. Я делаю кое-что там и после этого BackgroundWorker вызывает RunWorkerCompleted событие.

В основном потоке у меня есть функция Stop. Эта функция отключает Timer. Но я хочу дождаться BackgroundWorker, когда он работает.

Например:

public void Next()
{

    // Start the asynchronous operation
    if (!this._backgroundWorker.IsBusy)
        this._backgroundWorker.RunWorkerAsync();

}

private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    DoSomething();

}


private void _backgroundWorker_RunWorkerCompleted(object sender, 
    RunWorkerCompletedEventArgs e)
{
    DoSomethingElse();
}

public void Stop()
{
    this._timer.Enabled = false;
}

Итак, мой вопрос: как ждать RunWorkerCompleted событие BackgroundWorker? Мне нужно подождать, пока DoSomethingElse(); не закончится.

Спасибо

Ответы [ 4 ]

2 голосов
/ 07 мая 2011

Обработка события BackgroundWorker.RunWorkerCompleted , которое происходит, когда фоновая операция завершилась, была отменена или вызвала исключение.

// This event handler deals with the results of the
// background operation.

private void backgroundWorker1_RunWorkerCompleted(
    object sender, RunWorkerCompletedEventArgs e)
{
    // First, handle the case where an exception was thrown.
    if (e.Error != null)
    {
    }
    else if (e.Cancelled)
    {
        // Next, handle the case where the user canceled 
        // the operation.
        // Note that due to a race condition in 
        // the DoWork event handler, the Cancelled
        // flag may not have been set, even though
        // CancelAsync was called.
    }
    else
    {
        // Finally, handle the case where the operation 
        // succeeded.
    }

}
1 голос
/ 08 мая 2011

Я думаю, что свойство BackgroundWorker.IsBusy - единственный член, который может помочь вам в этом случае. Надеюсь, что ниже логика будет делать то, что вам нужно.

//Add a class member
private bool stopped;

public void Stop() 
{    
     if (!this._backgroundWorker.IsBusy)
     {
         this._timer.Enabled = false; 
         stopped = false;
     }
     else
     {
         stopped = true;
     }

} 

private void _backgroundWorker_RunWorkerCompleted(object sender,      RunWorkerCompletedEventArgs e) 
{     
     DoSomethingElse(); 

    if (stopped)
    {
             this._timer.Enabled = false; 
             stopped = false;
    }
} 
1 голос
/ 07 мая 2011

Если вам требуются только два потока, разрешите поток, который вызвал this._backgroundWorker.RunWorkerAsync ();умереть после того, как он вызовет этот метод, и вызвать все, что вы хотите, после DoSomethingElse ();в том же блоке, что и ниже

        private void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

DoSomethingElse();
DoSomethingAfterSomethingElse();

        }

В противном случае вы останавливаете поток, чтобы запустить другой, а затем возвращаетесь, что противоречит цели нескольких потоков?

0 голосов
/ 03 февраля 2017

Вот способ остановить / заморозить основной поток, пока ваш фоновый работник не завершит работу:

public void Stop()
{
    if (!_backgroundWorker.IsBusy)
    {
        _timer.Enabled = false;

        // Stop/Freeze the main thread until the background worker finishes 
        while (_backgroundWorker.IsBusy)
        {
            Thread.Sleep(100);
        }
    }
}

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

private bool _canClose;

public void Stop()
{
    if (!_backgroundWorker.IsBusy)
    {
        _timer.Enabled = false;
        // Don't let the user do anything in the form until the background worker finishes
        this.IsEnabled = false;
        _label.Text = "Waiting for the process to finish";
        _canClose = false; 
    }
 }
private void _backgroundWorker_RunWorkerCompleted(object sender,
    RunWorkerCompletedEventArgs e)
{
    DoSomethingElse();
    // Allow the user to close the form
    this.IsEnabled = true;
    _canClose = true;
}

private void MainWindow_Closing(object sender, CancelEventArgs e)
{
    e.Cancel = !_canClose;
}
...