Обработка исключений 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
, и завершенный обработчик все равно будет работать.