我正在使用以下组件:
我正在使用backgroundworker调用库方法。库会抛出异常,但永远不会调用RunWorkerCompleted处理程序。
捕获异常的唯一方法是使用try / catch块包围我的DoWork处理程序代码。
是否误解了RunWorkerCompletedEventArgs.Error属性?是不是用于获取BackgroundWorker捕获的异常?
Codesample:
static BackgroundWorker w = new BackgroundWorker();
w.DoWork += new DoWorkEventHandler(w_DoWork);
w.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(w_RunWorkerCompleted);
w.RunWorkerAsync();
static void w_DoWork(object sender, DoWorkEventArgs e)
{
MyClass m = new MyClass();
w.result = m.Compute();
}
static void w_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
HandleException(e.Error);
}
/* result related code */
}
static void HandleException(Exception e)
{
ExceptionPolicy.HandleException(e, "MyPolicy");
}
以上示例导致我的控制台应用程序终止。 vs2010输出绝对没有写入(只有默认输出)。
那么问题出在哪里?
//编辑:此代码段用于捕获库的异常。
static void w_DoWork(object sender, DoWorkEventArgs e)
{
try
{
MyClass m = new MyClass();
w.result = m.Compute();
}catch(Exception e){ }
}
答案 0 :(得分:7)
这是BackgroundWorker的正确模式。
我怀疑问题是你的Main
方法在BW完成之前就已退出。
RunWorkerAsync
将立即返回,如果您没有等待Main
,那么您的流程将会结束,甚至可能在BW启动之前,从不介意完成。
尝试在Console.ReadLine
方法的末尾添加Main
。
出于兴趣:
BW在控制台应用和Windows应用中的行为有所不同。如果你使用WinForms或WPF应用程序,你的UI线程上会有一个派生的SynchronizationContext,BW会将RunWorkerCompleted
封送回UI线程并在那里运行它。这是BW的主要好处之一。
在Console App中,使用默认的SynchronizationContext,并将RunWorkerCompleted
编组到线程池线程中。这意味着您可以阻止Main
线程,并且已完成的处理程序仍将运行。