等待多个任务会比第一个例外更多吗? [英] Will awaiting multiple tasks observe more than the first exception?

查看:191
本文介绍了等待多个任务会比第一个例外更多吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我的同事和我讨论了如何正确处理C#5.0 async 方法中的异常,我们想知道等待多个任务是否同时观察到不能得到的异常



考虑以下代码片段:

  async Task ExceptionMethodAsync()
{
等待Task.Yield();
throw new Exception();
}

异步任务CallingMethod()
{
try
{
var a = ExceptionMethodAsync();
var b = ExceptionMethodAsync();

await Task.WhenAll(a,b);
}
catch(Exception ex)
{
//捕获第一个异常(不管第一是什么意思)

}
}

现在第二个任务会发生什么?两者都将处于错误的状态,但是现在观察到或不可观察到的第二个任务是例外?

解决方案

Task.WhenAll 返回任务,像所有任务一样, Exception 属性保存一个 AggregateException 结合所有异常。



当您等待这样的任务只有第一个例外才会被抛出。 >


...无论是因为子任务出现故障,还是因为组合器像Task.WhenAlll,单个任务可能代表多个操作,而不止于其中一个可能有错。在这种情况下,为了不丢失异常信息(这对于验证后调试很重要),我们希望能够表示多个异常,因此我们选择AggregateException的包装器类型。



...考虑到,再次有选择总是抛出第一个或总是抛出一个聚合,为了等待,我们选择总是抛出第一个


from .NET 4.5中的任务异常处理



由你自己选择是否要处理第一个使用等待任务; (在大多数情况下为true)或使用 task.Exception 处理所有(如我的例子下面),但是在这两种情况下, a b 不会引发 UnobservedTaskException

  var task = Task.WhenAll(a,b); 
try
{
等待任务;
}
catch
{
Trace.WriteLine(string.Join(,,task.Exception.Flatten()。InnerExceptions.Select(e => e.Message )));
}


Today my colleagues and I discussed how to handle exceptions in C# 5.0 async methods correctly, and we wondered if awaiting multiple tasks at once also observes the exceptions that do not get unwrapped by the runtime.

Consider the following code snippet:

async Task ExceptionMethodAsync()
{
    await Task.Yield();
    throw new Exception();
}

async Task CallingMethod()
{
    try
    {
        var a = ExceptionMethodAsync();
        var b = ExceptionMethodAsync();

        await Task.WhenAll(a, b);
    }
    catch(Exception ex)
    {
        // Catches the "first" exception thrown (whatever "first" means)

    }
}

What happens to the second task now? Both will be in a faulted state, but is the second task's exception now observed or unobserved?

解决方案

Task.WhenAll returns a task and like all tasks the Exception property holds an AggregateException that combines all exceptions.

When you await such a task only the first exception will actually be thrown.

... Whether because of child tasks that fault, or because of combinators like Task.WhenAlll, a single task may represent multiple operations, and more than one of those may fault. In such a case, and with the goal of not losing exception information (which can be important for post-mortem debugging), we want to be able to represent multiple exceptions, and thus for the wrapper type we chose AggregateException.

... Given that, and again having the choice of always throwing the first or always throwing an aggregate, for "await" we opt to always throw the first

from Task Exception Handling in .NET 4.5

It's up to you to choose if you want to handle just the first using await task; (true in most cases) or handle all using task.Exception (as in my example below), but in both cases a and b would not raise an UnobservedTaskException.

var task = Task.WhenAll(a, b);
try
{
    await task;
}
catch
{
    Trace.WriteLine(string.Join(", ", task.Exception.Flatten().InnerExceptions.Select(e => e.Message)));
}

这篇关于等待多个任务会比第一个例外更多吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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