WithAggregatedExceptions 异步捕获包含多个异常的AggregateException

static void Main(string[] args)
{
    var t = ShowPageLengthTaskAsync("https://www.cnblogs.com/trust-freedom/p/11934262.html");
    var t1 = ShowPageLengthTaskAsync("http://www.google.com");
    var t2 = ShowPageLengthTaskAsync("http://www.google.com");
    var t3 = ShowPageLengthTaskAsync("http://mebook.cc");
    try
    {
        Task.WhenAll(t, t1, t2, t3).WithAggregatedExceptions().GetAwaiter().GetResult();
    }
    catch (AggregateException ex)
    {
        Console.WriteLine("Caught {0}", ex.GetAggregateExceptionMsg());
    }
}

private static async Task<int> ShowPageLengthTaskAsync(string url)
{
    using (var client = new HttpClient())
    {
        var str = await client.GetStringAsync(url);
        Console.WriteLine($"Get Page Lenght: {url}({str.Length})");
        return str.Length;
    }
}
/// <summary>
/// 从任务失败重新包装多个异常。
/// 异步捕获包含多个异常的AggregateException
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public static AggregateExceptionAwaitable WithAggregatedExceptions(this Task task)
{
    if (task == null)
    {
        throw new ArgumentNullException("task");
    }
    return new AggregateExceptionAwaitable(task);
}
/// <summary>
/// 获取多个异常的信息
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
public static string GetAggregateExceptionMsg(this AggregateException e)
{
    return $"Caught {e.InnerExceptions.Count} exceptions:\r\n{string.Join(Environment.NewLine, e.InnerExceptions.Select(s => '\t' + s.Message))}";
}
public struct AggregateExceptionAwaitable
{
    private readonly Task _task;
    internal AggregateExceptionAwaitable(Task task)
    {
        _task = task;
    }
    internal AggregateExceptionAwaiter GetAwaiter()
    {
        return new AggregateExceptionAwaiter(_task);
    }
}
internal struct AggregateExceptionAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion
{
    private readonly Task _task;
    internal AggregateExceptionAwaiter(Task task)
    {
        _task = task;
    }
    public bool IsCompleted
    {
        get
        {
            return _task.GetAwaiter().IsCompleted;
        }
    }
    public void OnCompleted(Action continuation)
    {
        _task.GetAwaiter().OnCompleted(continuation);
    }

    public void UnsafeOnCompleted(Action continuation)
    {
        _task.GetAwaiter().UnsafeOnCompleted(continuation);
    }
    public void GetResult()
    {
        // 这将在失败时直接引发AggregateException
        // 不像任务完成时,返回结果 _task.GetAwaiter().GetResult()
        _task.Wait();
    }
}
posted @ 2021-04-08 18:32  wesson2019  阅读(69)  评论(0编辑  收藏  举报