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();
}
}