2012-07-26 90 views
5

我想用ContinueWith()来包装可以由异步任务抛出的异常。如果我只是从继续操作中抛出东西似乎可行,但我的调试器声称这个异常是未处理的。我做错了什么或者这是一个Visual Studio问题?有没有更简单的方法来做到这一点,还是一种解决我的调试器问题的方法,以停止最终处理的异常?从ContinueWith抛出异常

下面的测试通过并打印出“捕获的包装异常如预期”,但是当我调试它时,throw new CustomException行显示为“未被用户代码处理”。

var task = DoWorkAsync().ContinueWith(t => { 
    throw new CustomException("Wrapped", t.Exception.InnerException); // Debugger reports this unhandled 
}, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously); 

try { 
    task.Wait(); 
    Assert.Fail("Expected work to fail"); 
} catch (AggregateException ag) { 
    if (!(ag.InnerException is CustomException)) 
     throw; 
} 
Console.WriteLine("Caught wrapped exception as expected"); 

回答

9

当“Just My Code”被启用时,Visual Studio在某些情况下会在引发异常的行上中断并显示一条错误消息,指出“未由用户代码处理的异常”。这个错误是良性的。您可以按F5继续并查看这些示例中演示的异常处理行为。为防止Visual Studio突破第一个错误,只需取消选中Tools,Options,Debugging,General下的“Just My Code”复选框。

http://msdn.microsoft.com/en-us/library/dd997415.aspx

4

你似乎没有用延续来“包装”异常,你似乎在延续中抛出异常。如果DoWorkAsync就是可以抛出一个异常,我想“包装”,在延续如下:

DoWorkAsync().ContinueWith(t=>{ 
Console.WriteLine("Error occurred: " + t.Exception); 
}, TaskContinuationOptions.OnlyOnFaulted); 

另外,如果你想“处理”的异步方法之外的异常,你可以这样做:

var task = DoWorkAsync(); 

task.Wait(); 
if(task.Exception != null) 
{ 
    Console.WriteLine("Error occurred: " + task.Exception); 
} 

如果要变换抛出的异常,你可以做这样的事情:

var task = DoWorkAsync().ContinueWith(t=>{ 
if(t.Exception.InnerExceptions[0].GetType() == typeof(TimeoutException)) 
{ 
    throw new BackoffException(t.Exception.InnerExceptions[0]); 
} 
}, TaskContinuationOptions.OnlyOnFaulted); 

而且你能搞定BackoffException这样的:

if(task.IsFaulted) 
{ 
    Console.WriteLine(task.Exception.InnerExceptions[0]); 
    // TODO: check what type and do something other than WriteLine. 
} 
+0

这里的关键,是你要访问Exception属性(或者通过访问任务。结果财产(一AggregateException中的异常重新抛出,如果你有一个任务)... – 2012-07-26 21:35:07

+0

DoWorkAsync()可以抛出一堆不同的异常,我只是试图将它们翻译成几个更高级别的“CustomException”,在调用代码中处理起来会比较麻烦,但实际上我不知道现在完全处理东西 所以我正在寻求将失败的任务转换成另一个失败的任务其中ex的类型ception是不同的。 – jtb 2012-07-26 21:38:29

+0

如果抛出一个CustomException,TPL子系统将把它包装在相同类型的AggregateException中,该类型将包装从DoWorkAsync抛出的异常。 – 2012-07-26 21:40:54