Необработанные исключения в 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, чтобы проверить наличие исключений в другом потоке.