c# - 使用 Task.ContinueWith 时如何避免嵌套的 AggregateException?

标签 c# exception asynchronous task-parallel-library

我在 .NET 4.5 C# 组件中有一个异步方法:

public async Task<T> GetResultAsync()
{
    return PerformOperationAsync();
}

如果 PerformOperationAsync 抛出异常,那么我可以在客户端捕获 AggregateException,将其解包并抛出原始异常。

但是,如果我有稍微复杂一点的代码:

public async Task<T> GetResultAsync()
{
    return PerformOperationAsync().ContinueWith(x =>
    {
        var result = x.Result;
        return DoSomethingWithResult(result);
    }, cancellationToken);
}

...然后万一发生异常,客户端会捕获一个嵌套的 AggregateException,因此它必须在获取原始异常之前将其展平。

是否应该避免这种行为,或者客户是否必须期待可能嵌套的 AggregateException 并调用 Flatten 来展开其所有级别?如果组件开发人员应该避免这种行为,那么在 ContinueWith 场景中处理它的正确方法是什么?我有很多类似的情况,所以我试图找到处理它们的最轻量级的方法。

最佳答案

C#5 async/await 将帮助您处理延续和正确的异常处理,同时简化代码。

public async Task<T> GetResultAsync()
{
    var result = await PerformOperationAsync().ConfigureAwait(false);
    return DoSomethingWithResult(result);
}

您的方法已被标记为异步,是预期的吗?


要保持继续,您可以提供一个 TaskContinuationOptionsOnlyOnRanToCompletion 值:

PerformOperationAsync().ContinueWith(x =>
{
    var result = x.Result;
    return DoSomethingWithResult(result);
}, TaskContinuationOptions.OnlyOnRanToCompletion);

或使用等待者引发原始异常

PerformOperationAsync().ContinueWith(x =>
{
    var result = x.GetAwaiter().GetResult();
    return DoSomethingWithResult(result);
}, cancellationToken);

关于c# - 使用 Task.ContinueWith 时如何避免嵌套的 AggregateException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29621079/

相关文章:

c# - 在 Environment.Exit 中模拟异常

java - 无法捕获异常

c# - 如何动态或在运行时设置 PropertyGrid 的 DefaultValueAttribute?

c# - visual studio xamarin.forms 中的秒表将 100 毫秒添加到 react 时间测试

返回类型有限的 C# 泛型

c# - EndReceive 永远不会返回 0,你怎么知道数据包在 tcp/ip 中何时完成?

asynchronous - 使用 OCaml Async 并发写入

c# - .NET GridView - 你能只右对齐一列吗?

c++ - 何时捕获 boost::bad lexical_cast

asynchronous - 如何从 Tokio 的非主线程运行异步任务?