Как мне "Thread.Join" BackgroundWorker? - PullRequest
4 голосов
/ 25 июня 2009

Скажем, я показываю пользователю форму и использую BackgroundWorker для выполнения какой-то закулисной работы.

Когда пользователь нажимает кнопку ОК, я не могу продолжить, пока не завершится BackgroundWorker. Если он не закончился, когда пользователь нажал Ok, я хочу показать WaitCursor до тех пор, пока он не закончил, а затем продолжить.

Какой лучший способ реализовать это?

Я знаю, что могу использовать простой старый поток, а затем сделать Thread.Join, но мне нравится BackgroundWorker.

Можно ли сделать это красиво?

Ответы [ 4 ]

8 голосов
/ 25 июня 2009

Вы можете использовать этот код вместо BW

var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(state =>
                {
                    Thread.Sleep(5000);//LongRunning task, async call
                    resetEvent.Set();
                });
resetEvent.WaitOne();// blocking call, when user clicks OK 
8 голосов
/ 25 июня 2009

В идеале вы должны отключить все соответствующие элементы управления в форме, а затем снова включить их после завершения BackgroundWorker. Таким образом, вы не получите заблокированный пользовательский интерфейс - у вас может быть кнопка отмены и т. Д.

Если вы хотите фактически блокировать, пока он не закончится, вы можете просто запустить задачу синхронно, чтобы начать с.

2 голосов
/ 27 июня 2009

Вы можете проверить, работает ли BackgroundWorker с проверкой в ​​обработчике событий btnOK_Click, чтобы увидеть, имеет ли значение bw.IsBusy значение true. Если это так, измените курсор и установите логический флаг, который указывает, что обработчик OK ожидает. Когда BackgroundWorker завершит свою работу, проверьте, ожидал ли ok, и если да, установите флаг в false, измените курсор и выполните задание кнопки OK. : -)

0 голосов
/ 25 июня 2009

Я бы просто использовал логические флаги и блокировку.

object waitlock = new object();
bool isBackgroundWorkerCompleted = false;
bool isOKButtonPressed = false;

private void onPress(...) 
{
    lock(waitlock) 
    {
      isOKButtonPressed = true;
      if (isBackgroundWorkerCompleted) DoNextStep();
      else cursor.Wait(); //psuedo-code - use whatever the actual call is...
    }
}

Фоновый поток выполняет тот же трюк (просто не забудьте BeginInvoke вернуться к основному потоку пользовательского интерфейса)

...