【发布时间】:2012-10-24 03:02:40
【问题描述】:
我正在为 WCF 调用编写某种包装器(使用 BackgroundWorker),以防止 GUI 在调用过程中冻结。它主要按应有的方式工作,但是当 WCF 调用引发异常时,我遇到了 BackgroundWorker 的问题。如果 DoWork 中发生异常,我可以在 RunWorkCompleted 中检测到它,但将其重新扔到 GUI 中不起作用。我读过很多帖子,有人提到这应该可行。
包装器代码(请注意,WCF 调用由抛出的异常表示):
private void GetSomething(Action<IEnumerable<int>> completedAction)
{
BackgroundWorker b = new BackgroundWorker();
b.DoWork += (s, evt) => { throw new Exception(); evt.Result = new List<int> { 1, 2, 3 }; };
b.RunWorkerCompleted += (s, evt) =>
{
if (evt.Error == null && completedAction != null)
{
completedAction((IEnumerable<int>)evt.Result);
}
else if(evt.Error != null)
{
throw evt.Error;
}
};
b.RunWorkerAsync();
}
在 Windows 窗体中调用代码:
private void button3_Click(object sender, EventArgs e)
{
try
{
GetSomething(list =>
{
foreach (int i in list)
{
listView1.Items.Add(new ListViewItem(i.ToString()));
}
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
在调试时,我得到:
- “在 DoWork 中引发了 'System.Exception' 类型的异常”
- “抛出 'System.Exception' 类型的异常”在 throw evt.Error
- Main 方法中的 Application.Run(new Form1()) 中的“TargetInvocationException 未处理”
我做错了什么?我想在 Windows 窗体中捕获异常。
【问题讨论】:
-
您应该在 RunWorkerCompleted 中处理异常。您是否有任何具体原因要重新抛出。
-
@CodeIgnoto:我的想法是将这个决定推给调用者。我不想使用这个包装器中的消息框。它应该尽可能与 GUI 无关
-
根据我的经验,在 RunWorkerCompleted 代码中抛出的任何异常都会导致应用程序崩溃。所以去任务或在那里处理它。如果您在启动时使用 while(true)Application.DoEvents() 而不是 Application.Run() ,则可以尝试在 doevents 周围捕获,它会抓住您刚刚重新抛出的异常。但是某些代码可能无法通过这种“消息”循环按预期运行。
标签: c# exception backgroundworker