Task是不同于Thread的。
个人理解:
Task是对ThreadPool 池化线程更高的封装,具有更多的API可以供我们进行调用。
Task通俗一点将:我(Program)将会在未来的某个时间完成你给我的工作。
//Task接受一个委托。
public Task (Action action);
//The work to execute asynchronously
//工作会异步的进行执行
//接受一个Action无返回值的委托。
public static Task Run (Action action);
比如一个例子 -> 我接了一个私活儿,我需要进行如下的工作:
- 沟通需求
- 设计功能
- 谈价格
- 50%的前期开发费
- 开发项目
- 交接项目,收尾款
在第五步的时候,项目团队可以同时进行多个功能模块进行开发。
//开发Coding函数
private static void Coding(string name, string projectName)
{
Console.Write($"功能开发人员 ->{name},当前项目名称 ->{projectName},当前工作线程 ->{Thread.CurrentThread.ManagedThreadId}");
}
- Main函数:
Console.WriteLine("开始进行沟通!*******************");
Console.WriteLine("开始进行设计");
Console.WriteLine("开始进行分配人员干活。");
Task.Run(() =>
{
Coding("Leo", "DataBAse");
})
Task.Run(() =>
{
Coding("Aaron", "UI");
})
Task.Run(() =>
{
Coding("Tom", "WebApi");
})
Console.WriteLine("项目结束,收工。");
此处会产生一个问题,因为线程是异步的。执行的过程可能是:
- 沟通
- 设计
- 干活
- 手工
- 开发
因此我们需要使用 Task.WaitAll(param [] Task) 在程序有些地方进行异步执行。它接收一个 Task数组。
Task.WaitAll(param [] Task)<阻塞线程>代表所有的Task都执行完毕才能执行下面的语句。
Task.WaitAny(param [] Task) <阻塞线程>代表任意一个Task完成,就执行下面的语句。
让我们改造一下Main函数的代码。
Console.WriteLine("开始进行沟通!*******************");
Console.WriteLine("开始进行设计");
Console.WriteLine("开始进行分配人员干活。");
List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() =>
{
Coding("Leo", "DataBAse");
}));
tasks.Add(Task.Run(() =>
{
Coding("Aaron", "UI");
}));
tasks.Add(Task.Run(() =>
{
Coding("Tom", "WebApi");
}));
Task.WaitAll(tasks.ToArray());
Console.WriteLine("项目结束,收工。");
但是又会产生一个问题,Task.WaitAll()会产生阻塞,那如果我们在做form窗体或者做web处理请求时改怎么处理呢。如果产生了阻塞,我们的form窗体就没办法拖动。web处理请求进来必须等待Task完成才能做别的事情。所以我们还需要再优化一下Main函数。
Console.WriteLine("开始进行沟通!*******************");
Console.WriteLine("开始进行设计");
Console.WriteLine("开始进行分配人员干活。");
//在这里用一个新的线程去跑。
Task.Run(()=>{
List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() =>
{
Coding("Leo", "DataBAse");
}));
tasks.Add(Task.Run(() =>
{
Coding("Aaron", "UI");
}));
tasks.Add(Task.Run(() =>
{
Coding("Tom", "WebApi");
}));
Task.WaitAll(tasks.ToArray());
Console.WriteLine("项目结束,收工。");
});
但是个人不推荐。在开发中,我们尽量不要线程套线程。
我们有更优秀的封装。
TaskFactory tf = new TaskFactory();
//任意一个线程完成后,执行里面的过程
tf.ContinueWhenAny(tasks.ToArray() , t=>{
//todoSometing
});
//所有线程完成后,执行里面的过程
tf.ContinueWhenAll(tasks.ToArray(),t=>{
//todoSometing
});