Необработанные исключения в BackgroundWorker
мое приложение WinForms использует ряд BackgroundWorker предметы для извлечения информации из базы данных. Я использую BackgroundWorker, потому что он позволяет пользовательскому интерфейсу оставаться разблокированным во время длительных запросов к базе данных, и это упрощает потоковую модель для меня.
Я получаю случайные DatabaseExceptions в некоторых из этих фоновых потоков, и я был свидетелем по крайней мере одного из этих исключений в рабочем потоке во время отладки. Я довольно уверен в этом исключения-это тайм-ауты, которые, я полагаю, разумно ожидать время от времени.
мой вопрос о том, что происходит, когда необработанное исключение возникает в одном из этих фоновых рабочих потоков.
Я не думаю, что могу поймать исключение в другом потоке, но могу ли я ожидать, что мой WorkerCompleted метод будет выполнен? Есть ли какое-либо свойство или метод BackgroundWorker, который я могу опросить для исключений?
5 ответов:
Если операция вызывает исключение, что ваш код не обрабатывает тег
BackgroundWorker
ловит исключение и передает его вRunWorkerCompleted
обработчик событий, где он представлен как свойство ошибкиSystem.ComponentModel.RunWorkerCompletedEventArgs
. Если вы работаете под отладчиком Visual Studio, отладчик сломается в точке обработчика событий DoWork, где было необработанное исключение поднятый.http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx
я полностью использую
BackgroundWorker
на протяжении многих лет и действительно знаю это в глубине души.совсем недавно, мой
RunWorkerCompleted
не пойматьe.Error
когда я простоThrow New Exception("Test")
наDoWork
. Однако возникло необработанное исключение. Лови вDoWork
- это не лучшая практика, таким образомe.Error
нет смысла.когда я пытаюсь создать новый
Form
новыеBackgroundWorker
,e.Error
наRunWorkerCompleted
успешно справились. Там должно быть что-то не так в моей сложнойBackgroundWorker
.после a несколько дней гуглил и отлаживал, пробовал ошибку. Я нашел это в моем
RunWorkerCompleted
:
- проверить
e.Error
во-первых, тогдаe.Cancelled
и наконецe.Result
- не получается
e.Result
еслиe.Cancelled = True
.- не получается
e.Result
еслиe.Error
неnull
(илиNothing
)*** * вот где я скучаю. Если вы пытаетесь использовать
e.Result
еслиe.Error
неnull
(илиNothing
), необработанное исключение заброшенный.
обновление: В
e.Result
получить свойство .NET дизайн его для проверкиe.Error
во-первых, если получил ошибку, то они будут повторно бросить то же исключение изDoWork
. Вот почему мы получаем необработанное исключение вRunWorkerCompleted
но на самом деле исключение приехал изDoWork
.вот лучшая практика, чтобы сделать в
RunWorkerCompleted
:If e.Error IsNot Nothing Then ' Handle the error here Else If e.Cancelled Then ' Tell user the process canceled here Else ' Tell user the process completed ' and you can use e.Result only here. End If End If
если вы хотите объект, который доступен для всех DoWork, ProgressChanged и RunWorkerCompleted, используйте вот так:
Dim ThreadInfos as Dictionary(Of BackgroundWorker, YourObjectOrStruct)
вы можете легко получить доступ к
ThreadInfos(sender).Field
везде, где вы хотите.
по умолчанию он будет пойман и сохранен BackgroundWorker. От MSDN:
Если операция вызывает исключение, которое ваш код не обрабатывает, BackgroundWorker ловит исключение и передает его в обработчик событий RunWorkerCompleted, где оно предоставляется как свойство Error системы.ComponentModel.RunWorkerCompletedEventArgs. Если вы работаете под отладчиком Visual Studio, отладчик сломается в точке обработчика событий DoWork где возникло необработанное исключение.
Как уже отмечалось:
Если операция вызывает исключение что ваш код не обрабатывает, в BackgroundWorker перехватывает исключение и передает его в Обработчик события RunWorkerCompleted , где он выставляется как ошибка собственность Система.ComponentModel.RunWorkerCompletedEventArgs.
Это важно, когда вы взаимодействуете с исходным потоком. Например, если вы хотите, чтобы результат вашего исключения будет написано в какой-то метке на вашей форме, вот когда вы не должны ловить исключение в DoWork BackgroundWorker, а вместо этого обрабатывать e.Error от RunWorkerCompletedEventArgs.
Если вы проанализируете код BackgroundWorker с отражателем, вы можете увидеть, что все это обрабатывается довольно просто: Ваш DoWork выполняется в блоке try-catch, и исключение просто передается в RunWorkerCompleted. Вот почему я не согласен с "предпочтительным" методом всегда ловить все исключения в случае метода dowork.
короче, чтобы ответить на исходный вопрос:
да - вы можете рассчитывать на то, что ваш RunWorkerCompleted всегда будет уволен.
использовать Эл.Ошибка из RunWorkerCompleted, чтобы проверить наличие исключений в другом потоке.