简体   繁体   English

从ContinueWith中抛出异常

[英]Throwing exceptions from ContinueWith

I am trying to wrap the exceptions that can be thrown by an async task using ContinueWith() . 我试图使用ContinueWith()包装可以由异步任务抛出的异常。 If I just throw from the continuation action things seem to work, but my debugger claims the exception is unhandled. 如果我只是从延续动作抛出事情似乎工作,但我的调试器声称异常未处理。 Am I doing something wrong or is this a Visual Studio problem? 我做错了什么或这是一个Visual Studio问题? Is there a cleaner way to do this, or a way to work around my debugger stopping on what is ultimately a handled exception? 有没有更简洁的方法来做到这一点,或者一种解决我的调试器停止最终处理的异常的方法?

The test below passes and prints "caught wrapped exception as expected", but when I debug it the throw new CustomException line shows as "unhandled by user code". 下面的测试传递并打印“按预期捕获包装的异常”,但是当我调试它时, throw new CustomException行显示为“ 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");

When "Just My Code" is enabled, Visual Studio in some cases will break on the line that throws the exception and display an error message that says "exception not handled by user code." 启用“只是我的代码”时,Visual Studio在某些情况下会在抛出异常的行上中断,并显示一条错误消息,指出“异常不由用户代码处理”。 This error is benign. 这个错误是良性的。 You can press F5 to continue and see the exception-handling behavior that is demonstrated in these examples. 您可以按F5继续并查看这些示例中演示的异常处理行为。 To prevent Visual Studio from breaking on the first error, just uncheck the "Just My Code" checkbox under Tools, Options, Debugging, General. 要防止Visual Studio在第一个错误中出现问题,只需取消选中Tools,Options,Debugging,General下的“Just My Code”复选框。

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

You don't appear to be "wrapping" the exceptions with a continuation, you seem to be throwing the exception in the continuation. 您似乎没有用延续“包装”异常,您似乎在延续中抛出异常。 If DoWorkAsync is what can throw an exception, I would "wrap" that in a continuation as follows: 如果DoWorkAsync是可以抛出异常的东西,我会在一个延续中“包装”它,如下所示:

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

Alternatively, if you want to "handle" the exception outside the async method, you could do this: 或者,如果要在异步方法之外“处理”异常,可以执行以下操作:

var task = DoWorkAsync();

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

If you want to transform the thrown exception, you could do something like this: 如果要转换抛出的异常,可以执行以下操作:

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

And you could handle that BackoffException like this: 你可以像这样处理BackoffException

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM