Обработка исключений BackgroundWorker

Я работаю со следующими компонентами:

  • Библиотека (которая генерирует исключение)
  • тестовая консоль для проверки моего ведения журнала
  • блоки приложений для обработки исключений корпоративной библиотеки
  • блокирование приложений регистрации в корпоративной библиотеке

Я вызываю библиотечный метод с помощью фонового рабочего. Библиотека выдает исключение, но обработчик RunWorkerCompleted никогда не вызывается.

Единственный способ поймать исключение - окружить мой код обработчика DoWork блоком try/catch.

Не понял ли свойство RunWorkerCompletedEventArgs.Error? Разве это не для получения исключений, которые были пойманы BackgroundWorker?

Codesample:

static BackgroundWorker w = new BackgroundWorker();

w.DoWork += new DoWorkEventHandler(w_DoWork);
w.RunWorkerCompleted += 
   new RunWorkerCompletedEventHandler(w_RunWorkerCompleted);
w.RunWorkerAsync();



static void w_DoWork(object sender, DoWorkEventArgs e)
{
   MyClass m  = new MyClass();
   w.result = m.Compute();
}

static void w_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   if (e.Error != null)
   {
      HandleException(e.Error);
   }

   /* result related code */

}


static void HandleException(Exception e)
{
   ExceptionPolicy.HandleException(e, "MyPolicy");
}

Вышеприведенный пример приводит к прекращению моего консольного приложения. Выход vs2010 ничего не пишет (только выход по умолчанию).

Итак, где проблема?

//Edit: этот фрагмент работает для исключения исключения библиотеки.

static void w_DoWork(object sender, DoWorkEventArgs e)
{
   try
   {
      MyClass m  = new MyClass();
      w.result = m.Compute();
   }catch(Exception e){ }

}

Ответ 1

Это правильный шаблон для BackgroundWorker.

Я подозреваю, что проблема заключается в том, что ваш метод Main выходит до завершения BW.

RunWorkerAsync вернется немедленно, и если вы не ожидаете в Main, то ваш процесс завершится, возможно, еще до того, как BW запустится, не пропустите.

Попробуйте добавить Console.ReadLine в конце вашего метода Main.


Из интереса:

BW ведет себя по-разному в приложении Console и в приложении Windows. Если вы используете WinForms или WPF-приложение, в вашем потоке пользовательского интерфейса будет создан производный SynchronizationContext, а BW будет маршализовать RunWorkerCompleted обратно в поток пользовательского интерфейса и запустить его там. Это одно из основных преимуществ BW.

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