我想等待抛出 AggregateException,而不仅仅是第一个异常 [英] I want await to throw AggregateException, not just the first Exception

查看:26
本文介绍了我想等待抛出 AggregateException,而不仅仅是第一个异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当等待一个有错误的任务(设置了异常的任务)时,await 将重新抛出存储的异常.如果存储的异常是 AggregateException,它将重新抛出第一个并丢弃其余的.

When awaiting a faulted task (one that has an exception set), await will rethrow the stored exception. If the stored exception is an AggregateException it will rethrow the first and discard the rest.

如何在使用await的同时抛出原来的AggregateException,才不会不小心丢失错误信息?

How can we use await and at the same time throw the original AggregateException so that we do not accidentally lose error information?

请注意,当然可以为此想出一些骇人听闻的解决方案(例如,在 await 周围尝试捕获,然后调用 Task.Wait).我真的很想找到一个干净的解决方案.这里的最佳做法是什么?

Note, that it is of course possible to think of hacky solutions for this (e.g. try-catch around the await, then call Task.Wait). I really wish to find a clean solution. What is the best-practice here?

我想过使用自定义等待程序,但内置的 TaskAwaiter 包含很多我不知道如何完全重现的魔法.它在 TPL 类型上调用内部 API.我也不想重现所有这些.

I thought of using a custom awaiter but the built-in TaskAwaiter contains lots of magic that I'm not sure how to fully reproduce. It calls internal APIs on TPL types. I also do not want to reproduce all of that.

如果你想玩的话,这里有一个简短的重现:

Here is a short repro if you want to play with it:

static void Main()
{
    Run().Wait();
}

static async Task Run()
{
    Task[] tasks = new[] { CreateTask("ex1"), CreateTask("ex2") };
    await Task.WhenAll(tasks);
}

static Task CreateTask(string message)
{
    return Task.Factory.StartNew(() => { throw new Exception(message); });
}

Run 中只抛出了两个异常中的一个.

Only one of the two exceptions is thrown in Run.

请注意,Stack Overflow 上的其他问题并未解决此特定问题.建议重复时请小心.

Note, that other questions on Stack Overflow do not address this specific problem. Please be careful when suggesting duplicates.

推荐答案

我不同意你的问题标题中暗示的 await 的行为是不受欢迎的.这在绝大多数情况下都是有意义的.在 WhenAll 情况下,您真的多久需要知道所有的错误详细信息,而不是一个?

I disagree with the implication in your question title that await's behavior is undesired. It makes sense in the vast majority of scenarios. In a WhenAll situation, how often do you really need to know all of the error details, as opposed to just one?

AggregateException 的主要困难在于异常处理,即您失去了捕获特定类型的能力.

The main difficulty with AggregateException is the exception handling, i.e., you lose the ability to catch a particular type.

也就是说,您可以使用扩展方法获得所需的行为:

That said, you can get the behavior you want with an extension method:

public static async Task WithAggregateException(this Task source)
{
  try
  {
    await source.ConfigureAwait(false);
  }
  catch
  {
    // source.Exception may be null if the task was canceled.
    if (source.Exception == null)
      throw;

    // EDI preserves the original exception's stack trace, if any.
    ExceptionDispatchInfo.Capture(source.Exception).Throw();
  }
}

这篇关于我想等待抛出 AggregateException,而不仅仅是第一个异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆