繁体   English   中英

等待所有任务不抛出异常

[英]Wait for all tasks without throwing exceptions

如果我await Task.WhenAll(tasks)它会在一项或多项任务失败时抛出异常。 我想手动检查每个任务对象。

通常catch(Exception)不是一个好主意。 在这种情况下这样做是否合理? 或者也许有另一种方法来等待所有任务? 我无法捕获AggregateException ,因为如果只有一个,它将被解包。

如何在异步方法中正确地做到这一点?

下面的AwaitCompletion扩展方法使用更通用的 API 满足您的要求。 它返回一个Task ,因此您仍然需要通过awaitTask.Wait()或其他方式await它。

using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

public static class TaskExtensions
{
    public static Task AwaitCompletion<T>(this ICollection<Task<T>> unfinishedTasks)
    {
        int remainingCount = unfinishedTasks.Count;
        var promise = new TaskCompletionSource<ICollection<Task<T>>>();
        var finishers = unfinishedTasks.Select(x => x.ContinueWith((task, state) =>
        {
            int postCount = Interlocked.Decrement(ref remainingCount);
            if (postCount == 0)
            {
                promise.SetResult(unfinishedTasks);
            }
        }, remainingCount));

        // force evaluation
        var _ = finishers.ToList();

        return promise.Task;
    }

    /// <summary>
    /// Unlike Task.Value, this doesn't wait for completion. Hence, it also doesn't
    /// throw exceptions.
    /// </summary>
    /// <returns>Value if completed, otherwise null (or default value if a value type)</returns>
    public static T GetResultOrDefault<T>(this Task<T> self)
    {
        if (self.IsCompletedSuccessfully)
        {
            return self.Result;
        }
        else
        {
            return default(T);
        }
    }
}

完成返回的Task值后, unfinishedTasks所有任务要么完成要么出错(或者如果您使用Task.Wait()超时,则仍然继续)。 AwaitCompletion不会抛出异常,等待它只会在达到超时时抛出异常。 要检索异常,请查看您传入的任务。

用法:

Task[] tasksToWaitFor = ...
await tasksToWaitFor.AwaitCompletion()
foreach (var task in tasksToWaitFor) 
{
    Console.WriteLine("result: {}", task.GetResultOrDefault());
}

GetResultOrDefault扩展方法很重要。 如果你直接点击Value ,它会在任务失败时抛出 AggregateException,OTOH GetResultOrDefault将返回 null。

暂时吞下异常

await Task.WhenAll(tasks).ContinueWith(delegate {} )

但请记住,然后单独检查所有任务并正确显示错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM