25

假设我有三个任务,abc。这三个都保证在 1 到 5 秒之间的随机时间抛出异常。然后我编写以下代码:

await Task.WhenAny(a, b, c);

这最终会从首先出现的任务故障中引发异常。因为这里没有try...catch,所以这个异常会冒泡到我的代码中的其他地方。

当剩下的两个任务抛出异常时会发生什么?这些未观察到的异常,不就是会导致整个进程被杀死吗?这是否意味着唯一的使用方法WhenAny是在一个try...catch块内,然后在继续之前以某种方式观察剩余的两个任务?

跟进:我希望答案适用于带有异步目标包的.NET 4.5TaskEx.WhenAny.NET 4.0(尽管在这种情况下显然使用)。

4

2 回答 2

27

当剩下的两个任务抛出异常时会发生什么?

这些Tasks 将在故障状态下完成。

这些未观察到的异常,不就是会导致整个进程被杀死吗?

不再。

在 .NET 4.0 中,Task析构函数会将其未观察到的异常传递给TaskScheduler.UnobservedTaskException,如果未处理,它将终止进程。

在 .NET 4.5 中,此行为已更改。现在,未观察到的异常被传递给TaskScheduler.UnobservedTaskException,但如果未处理,它们将被忽略。

于 2012-10-01T17:56:34.743 回答
5

是的,剩余的任务异常没有被观察到。在 .NET 4.5 之前,您有义务观察它们(不确定 .NET 4.5 的情况如何,但它发生了变化)。

我通常为自己编写一个辅助方法来完成这些即发即弃的任务:

    public static void IgnoreUnobservedExceptions(this Task task)
    {
        if (task.IsCompleted)
        {
            if (task.IsFaulted)
            {
                var dummy = task.Exception;
            }
            return;
        }

        task.ContinueWith(t =>
            {
                var dummy = t.Exception;
            }, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
    }

您可能希望包括登录生产应用程序。

于 2012-10-01T17:48:22.037 回答