Task中有几个非常方便的并行运行任务的方式,比如WhenAll(当所有Task都运行完毕RanToCompletion)、WhenAny(只要有一个Task运行完毕)等等。本篇就来介绍一下WhenAll和WhenAny。
static int TaskMethod(string name, int seconds)
{
Console.WriteLine("Task {0} 运行在线程 {1} 上。是否是线程池线程: {2}",
name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(seconds));
return 42 * seconds;
}
var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
var secondTask = new Task<int>(() => TaskMethod("Second Task", 2));
var whenAllTask = Task.WhenAll(firstTask, secondTask);
whenAllTask.ContinueWith(t =>Console.WriteLine("The first answer is {0}, the second is {1}", t.Result[0], t.Result[1]),
TaskContinuationOptions.OnlyOnRanToCompletion
);
firstTask.Start();
secondTask.Start();
这里设置了一个名字为whenAllTask的变量,他是用静态方法Task.WhenAll创建的第三个任务。需要注意的是,由于是基于前面两个任务创建的,因此返回的类型为 Task<int[]>。在firstTask和secondTask运行完毕后(WhenAll), 采用后续操作(ContinueWith),函数中的t其实也就是whenAllTask的传参。后续操作打印出whenAllTask中的Result数组成员,后续操作的状态条件为 whenAllTask的状态为OnlyOnRanToCompletion。
二、WhenAny
var tasks = new List<Task<int>>();
for (int i = 1; i < 4; i++)
{
int counter = i;
var task = new Task<int>(() => TaskMethod(string.Format("Task {0}", counter), counter));
tasks.Add(task);
task.Start();
}
while (tasks.Count > 0)
{
var completedTask = Task.WhenAny(tasks).Result;//这里的Result是指代Task<int>!
tasks.Remove(completedTask);
Console.WriteLine("A task has been completed with result {0}.", completedTask.Result);
}
首先建立一个Task List,名字为tasks。而后依次向里添加新任务实例,而且新任务的运行所需时间依次为1、2、3秒。而后,伦查tasks中的任务数量,在循环内 建立completedTask任务,用来表示任一个在tasks中已经完成操作的Task,如果一个任务都没运行完成,则completedTask。需要指出的是, 这里的Result和上例中的不同,上例中t.Result直接指代int[],即返回结果数组;而这里的WhenAny(tasks).Result指的是Task<int>,也就是完成的Task<int>实例 。