按完成顺序返回结果
static void Main(string[] args)
{
Console.WriteLine("TTTTT: 数据返回时,显示页面长度");
var task = ShowPageLengthTaskAsync("https://www.cnblogs.com/trust-freedom/p/12002089.html", "http://csharpindepth.com", "https://www.cnblogs.com/chenhuabin/p/11369359.html", "https://www.cnblogs.com/trust-freedom/p/11934262.html");
var total = task.GetAwaiter().GetResult();
Console.WriteLine("Total Length: {0}", total);
Console.WriteLine("TTTTT: 结束啦!!!");
Console.ReadKey();
}
![](https://img2020.cnblogs.com/blog/1865358/202104/1865358-20210408185309652-2036793419.png)
private static async Task<int> ShowPageLengthTaskAsync(params string[] urls)
{
try
{
var tasks = urls.Select(async url =>
{
using (var client = new HttpClient())
{
return await client.GetStringAsync(url);
}
}).ToList();
int total = 0;
foreach (var item in tasks.IncompletionOrder())
{
string page = await item;
Console.WriteLine("Get Page Lenght: {0}", page.Length);
total += page.Length;
}
return total;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return -1;
}
}
/// <summary>
/// 按完成的顺序将任务序列转换到新的集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">一般顺序的任务集合</param>
/// <returns>所得结果按完成的顺序排序</returns>
public static IEnumerable<Task<T>> IncompletionOrder<T>(this IEnumerable<Task<T>> source)
{
var inputs = source.ToList();
var boxes = inputs.Select(s => new TaskCompletionSource<T>()).ToList();
int curIndx = -1;
foreach (var item in inputs)
{
item.ContinueWith(completed =>
{
var nextBox = boxes[Interlocked.Increment(ref curIndx)];
PropagateResult(completed, nextBox);
}, TaskContinuationOptions.ExecuteSynchronously);
}
return boxes.Select(s => s.Task);
}
/// <summary>
/// 将给定任务的状态传播到源
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="completedTask">已经完成的任务</param>
/// <param name="source">任务完成的源</param>
private static void PropagateResult<T>(Task<T> completedTask, TaskCompletionSource<T> source)
{
switch (completedTask.Status)
{
case TaskStatus.RanToCompletion:
source.TrySetResult(completedTask.Result);
break;
case TaskStatus.Canceled:
source.TrySetCanceled();
break;
case TaskStatus.Faulted:
source.TrySetException(completedTask.Exception.InnerException);
break;
default:
throw new ArgumentException("任务未完成!");
}
}