我的WinForms应用程序使用许多BackgroundWorker对象从数据库中检索信息.我正在使用BackgroundWorker,因为它允许UI在长时间运行的数据库查询期间保持解除阻塞状态,并简化了我的线程模型.
我在其中一些后台线程中偶尔会遇到DatabaseExceptions,并且在调试时我在工作线程中至少目睹了其中一个异常.我相当有信心这些例外是超时,我认为它不时是合理的.
我的问题是当在其中一个后台工作线程中发生未处理的异常时会发生什么.
我不认为我可以在另一个线程中捕获异常,但我可以期望我的WorkerCompleted方法被执行吗?我是否可以查询异常的BackgroundWorker的任何属性或方法?
如果操作引发了代码无法处理BackgroundWorker
的异常,则捕获异常并将其传递到RunWorkerCompleted
事件处理程序,并将其作为Error属性公开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
.
经过几天的谷歌搜索和调试,尝试一个错误.我发现这个在我的RunWorkerCompleted
:
检查e.Error
第一个,然后是e.Cancelled
最后一个e.Result
不要得到e.Result
if e.Cancelled = True
.
不要得到e.Result
if e.Error
不是null
(或Nothing
)**
**这是我想念的地方.如果您尝试使用e.Result
if e.Error
不是null
(或Nothing
),则会抛出Unhandled Exception.
更新:
在e.Result
get属性.NET设计中首先检查它e.Error
,如果得到错误,那么它们将重新抛出相同的异常DoWork
.这就是为什么我们得到Unhandled异常,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事件处理程序,并将其作为System.ComponentModel.RunWorkerCompletedEventArgs的Error属性公开.如果您在Visual Studio调试器下运行,则调试器将在DoWork事件处理程序中引发未处理的异常的位置中断.