如何捕获已在任务的ContinueWith部分抛出的异常?

时间:2016-03-09 16:18:03

标签: c# exception-handling .net-4.0 task-parallel-library continuewith

button_click事件中,我开始Task以异步方式进行一些耗时的计算。我使用Task.ContinueWith并将TaskSheduler设置为继续使用UI同步上下文,以在Textbox中显示异步计算的结果。

现在让我们说最后一部分抛出一个像这样的例外:

private void button1_Click(object sender, EventArgs e)
{
   Task.Factory.StartNew(DoSomeCalculations).ContinueWith
      (t => { throw new Exception("Some Exception"); }, TaskScheduler.FromCurrentSynchronizationContext()); 
}

如果我启用调试选项“启用我的代码”,程序将停止并收到警告:“用户代码未处理异常”

但是如果我没有设置这个选项,Exception就会消失(没有程序崩溃,什么都没有)。

那么我如何/在哪里处理这个例外?

编辑:请注意,正如标记所示,我使用的是.NET-4.0

3 个答案:

答案 0 :(得分:1)

如果你想处理异常,那么在continuation本身内部有一个try / catch块,这样它就可以处理它自己的异常,或者为继续处理异常添加一个额外的延续。

请注意,如果您使用ContinueWith而不是{{1}}来添加延续,那么它通常会更简单,特别是在处理异常时,因为它会代表您添加延续。

答案 1 :(得分:1)

如果您使用的是.NET Framework 4.5,那么就有了处理Task对象的新方法。

private async void button1_Click(object sender, EventArgs e)
{
   await Task.Run(() =>
   {
       DoSomethingAsync()
   });
   //this line will run in UI thread
   throw new Exception("Some Exception");
}

请注意,当您使用async关键字时,在编译器创建的状态机内会吞下Task对象内发生的任何异常。但是这个异常是在Task对象中设置的,所以基本上你仍然可以使用Task对象引用异常。

供您参考的东西: http://blog.stephencleary.com/2012/02/async-and-await.html

答案 2 :(得分:0)

根据最佳实践,如果我们无法避免使用async void方法(特别是对于事件处理程序),则应该在该方法中实现try catch。但是你需要确保你调用的所有异步方法都有异步的Task方法签名,以便捕获抛出的异常。