c# - 在延续链中传播异常的正确方法是什么?

标签 c# exception task-parallel-library task continuation

在延续链中传播异常的正确方法是什么?

t.ContinueWith(t2 => 
{
     if(t2.Exception != null)
         throw t2.Exception;

     /* Other async code. */
})
.ContinueWith(/*...*/);   

t.ContinueWith(t2 => 
{
     if(t2.IsFaulted)
         throw t2.Exception;

     /* Other async code. */
})
.ContinueWith(/*...*/);

t.ContinueWith(t2 => 
{
     if(t2.Exception != null)
         return t2;

     /* Other async code. */
})
.ContinueWith(/*...*/);   

t.ContinueWith(t2 => 
{
     if(t2.IsFaulted)
         return t2;

     /* Other async code. */
})
.ContinueWith(/*...*/);


t.ContinueWith(t2 => 
{
     t2.Wait();

     /* Other async code. */
})
.ContinueWith(/*...*/);

t.ContinueWith(t2 => 
{     
     /* Other async code. */
}, TaskContinuationOptions.NotOnFaulted) // Don't think this one works as expected
.ContinueWith(/*...*/);

最佳答案

TaskContinuationOptions.OnlyOn... 可能会出现问题,因为如果不满足其条件,它们会导致延续被取消。在理解这一点之前,我编写的代码存在一些微妙的问题。

像这样的链式延续实际上很难做到正确。 到目前为止,最简单的修复方法是使用新的 .NET 4.5 await 功能。这使您几乎可以忽略正在编写异步代码的事实。您可以像在同步等效项中一样使用 try/catch block 。对于 .NET 4,可以使用 async targeting pack .

如果您使用的是 .NET 4.0,最直接的方法是从每个延续中的先行任务访问 Task.Result,或者,如果它没有返回结果,则使用 Task.Wait() 就像您在示例代码中所做的那样。但是,您最终可能会得到一个嵌套的 AggregateException 对象树,稍后您需要解开这些对象才能获得“真正的”异常。 (同样,.NET 4.5 使这更容易。虽然 Task.Result 抛出 AggregateExceptionTask.GetAwaiter().GetResult() — 这是否则等效——抛出底层异常。)

重申这实际上不是一个微不足道的问题,您可能对 Eric Lippert 关于 C# 5 异步代码中异常处理的文章感兴趣 herehere .

关于c# - 在延续链中传播异常的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15478882/

相关文章:

时间:2019-01-17 标签:c#wpfrichtextboxrunmouseup

c# - System.Text.Json 中是否可以进行多态反序列化?

c# - 如何将默认参数值设置为 BigInteger 类型?

.Net MVC4 - 如何以json格式返回异常?

c# - 限制通过并行任务库运行的事件任务数量的最佳方法

c# - Task.Factory.StartNew() 是否保证使用调用线程之外的另一个线程?

C# --> Java 代码生成器

java - JNA 捕获异常

python mysql自定义重新连接类不保持服务器连接打开

.net - 为什么*不*改变线程池(或任务)线程的优先级?