在使用C#的BackgroundWorker时需要在UI界面上显示DoWork中发生的异常,但怎么调试都无法跳转到界面上,异常也不会传递到RunWorkerCompleted方法中(e.Error为空)。在网上搜了很多类似的问题都没有找到答案(搜索方法不对,还是运气不好?),幸好在CSDN上搜到了一个相似的问题(如何统一处理BackgroundWork产生的异常),看到里面说使用“开始执行(不调试)”依然无法传递出异常,才想到可能是调试的问题,改用“开始执行(不调试)”(调试菜单,或CTRL+F5)成功解决这个问题。眼睛疼,睡觉。
DoWork方法执行时发生异常并中断程序运行,无法通过e.Error获取异常:
界面上显示错误:
补充:上述的解决方法在正式执行使用程序时还是发生了问题,没有将异常传递到Completed函数中。后来使用了一个稍微麻烦点的方法处理:在DoWork中使用try-catch对异常进行捕获,而不通过系统自动抛出(如上面所说,如果自己不进行捕获,调试时异常无法进入Completed函数处理),然后将捕获的异常赋值给e.Result返回给Completed函数进行处理,这样可以在调试模式下跟踪异常。为了便于使用,我自定义了一个额外的类WorkResult来表示DoWork返回的结果,其中包括一个Exception类型的属性Error用于保存捕获的异常和一个string类型(也可以是object类型)的属性Result用于保存DoWork需要返回的结果,最后在DoWork结束时将这个WorkResult的实例赋值给e.Result,这样就可以在RunWorkerCompleted函数中通过e.Result获取DoWork的操作结果和异常。部分代码如下。
定义WorkResult类并在DoWork函数中将异常和操作结果存入WorkResult实例中:
class WorkResult { public OperationType Operation { get; set; } public Exception Error { get; set; } public string Result { get; set; } }
private void DoWork(object sender, DoWorkEventArgs e) { WorkResult result = new WorkResult();//自定义返回结果,包括操作类型和WebService执行的结果 Exception ex = null; //DoWork需要处理的工作 .......... if (ex != null) { result.Error = ex; } e.Result = result; }
在RunWorkerCompleted函数中处理异常(通知用户发生错误或者其他操作):
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { //取得DoWork操作结果 WorkResult result = e.Result as WorkResult; if (result == null) { MessageBox.Show("发生错误!异步操作返回结果不是WorkResult类型。"); return; } if (result.Error != null) { //如果异步操作过程中发生异常,那么在这里处理 ...... } else { //对结果进行处理 ...... } }
如果大家对于这个问题有其他的解决方法还请在评论区贴出来,以便于遇到这个问题但不知道怎么解决的朋友使用,谢谢。