2013-04-17 4 views
0

У меня есть два фоновых работника в моем приложении, которые заполняют таблицу и отправляют сообщения журнала. Они передают эти данные с помощью «userState» метода ReportProgress.
Они подключены к основной нити через:C# Фоновый работник: исключение, когда Close() называется

msg_worker.DoWork    += message_worker_task; 
msg_worker.ProgressChanged  += msg_worker_ProgressChanged; 
msg_worker.RunWorkerCompleted += worker_completed; 

data_worker.DoWork    += data_worker_task; 
data_worker.ProgressChanged += data_worker_ProgressChanged; 
data_worker.RunWorkerCompleted += worker_completed; 

Они синхронизированы с использованием двух EventWaitHandle элементов, что они, установленные в конце их DoWork задачи:

private void message_worker_task(object sender, DoWorkEventArgs e) 
    { 
     try 
     { 
      while(..){ 
       // do work 
       bw.ReportProgress(10, new String("my message to append")); 
      } 
     } 
     finally 
     { 
      e.Result = 0; 
      msg_done.Set(); // EventWaitHandle 
     } 
    } 

Прогресс изменил делегаты вставки данных/войдите в компоненты, видимые пользователю.

Теперь проблема в том, что при нажатии на кнопку Quit в моем UI, я на этих 2-х потоков, как это:

private void wait_threads() 
    { 
     int timeout = 30000; 
     Cursor.Current = Cursors.WaitCursor; 
     if (data_worker.IsBusy && !data_worker.CancellationPending) 
     { 
      data_worker.CancelAsync(); 
      data_done.WaitOne(timeout); 
     } 
     if (msg_worker.IsBusy && !msg_worker.CancellationPending) 
     { 
      msg_worker.CancelAsync(); 
      msg_done.WaitOne(timeout); 
     } 
     Cursor.Current = Cursors.Default; 
    } 

Это, кажется, работает (я использую его в других местах код), но в этом случае «прекращения» у меня возникло исключение, говоря, что я попытался вставить данные в компонент журнала, который у меня есть. Этот компонент обрабатывается делегатом RunWorkerCompleted.

Код, который запускается на выполнение, когда Бросить нажата эта:

private void quit_Click(object sender, EventArgs e) 
    { 
     wait_threads(); // blocks until threads are finished 
     Close(); 
    } 

Я думаю, что я понял, что во время ожидания потоков завершения, они посылают последнее событие: RunWorkerCompleted. Проблема в том, что я вхожу в процесс Close() в моей форме, что означает, что форма не находится в правильном состоянии. Более того, если я проверить e.Cancelled флаг в функции worker_completed, я вижу это как ложь ...

Что я могу сделать, чтобы убедиться, что RunWorkerCompleted обрабатывается перед тем моя Close() функция запускается на выполнение? (вернее, не обрабатывается вообще, потому что мы уходим).

+0

Есть ли опечатка? waith_threads() вместо wait_threads()? – Guido

+0

Да;) Я сократил код и пропустил это. – Gui13

ответ

0

Я думаю, вы можете проверить свойство Отмена Ожидание перед вызовом ReportProgress.

while(..){ 
    if (!bw.CancellationPending) 
       bw.ReportProgress(10, new String("my message to append")); 
} 
+0

На самом деле, возможно, я ошибся. Я понял, что это RunWorkerCompleted, который создает исключение. В коде я вижу, что я также использую компоненты. – Gui13

+0

Что делать, если вы положили 'WaitOne' перед' Close() 'на' WaitHandle', который установлен в 'DataWorkerComplete'? – misleadingTitle

Смежные вопросы