什么是Task?
Task是用来实现多线程的类,在以前当版本中已经有了Thread及ThreadPool,为什么还要提出Task类呢,这是因为直接操作Thread及ThreadPool,向线程中传递参数,获取线程的返回值及线程当启停时都非常的麻烦,所以微软的工程师对Thread进行了再封装,这就是Task,可以这么说Task是架构在Thread之上的,所以多线程时Task是我们的首选。
任务的线程是后台线程。
本质上讲,任务就是一个线程池的增强版API 。
线程池的缺点
1、线程池获取结果并不方便
2、异步处理不方便
3、连续的异步操作不方便
目的:
场景1: 3个并发请求,通过3个接口获取数据,我们希望得到所有接口的数据进行下一步业务处理。
场景2: 3个并发请求,只要其中某一个完成了,就触发一个事件结果。
Task的声明
Task的声明有两种方式:
a.通过new 的方式来声明
Task obj = new Task();
b.通过Task.Factory.StartNew的方式来声明
Task.Factory.StartNew(MyMethod);
获取任务返回值
Task<string> task = new Task<string>(() =>
{
DoSomething();
return "此处为执行完成的结果";
});
task.Start();
Console.WriteLine(task.Result);
任务的回调
task.ContinueWith
(1)支持1个 task 接多个ContinueWith ;
(2)ContinueWith返回下一代 task,下一代可以继续ContinueWith,类似于Lambda;
Task<string> task = new Task<string>(() =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
return "boy,";
});
task.ContinueWith((t) =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
Console.WriteLine(t.Result + "come on.");
});
task.Start();
Console.ReadLine();
Task的线程等待和延续
Wait
针对单个Task的实例,可以让某一个线程进入等待。
WaitAny
执行的所有线程中只要有一个线程结束,主线程就执行,否则就卡住。
WatiAll
表示任务列表中所有的任务都已经结束后,主线程恢复。
WhenAny
表示任务列表中任何一个任务结束后,配合ContinueWith进行回调触发。
WhenAll
表示任务列表中所有任务都结束后,配合ContinueWith进行回调触发。
注意:WhenAny和WhenAll,都是开启一个新线程执行,不卡顿主线程。
TaskFactory
TaskFactory可以开启线程,当然也对应线程的等待和延续。
ContinueWhenAny:等价于Task的WhenAny+ContinueWith
ContinueWhenAll:等价于Task的WhenAll+ContinueWith
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
public static void Main(string[] args)
{
List<Task<string>> taskList = new List<Task<string>>();
Task<string> t1 = new Task<string>(() =>
{
return GetName();
});
Task<string> t2 = new Task<string>(() =>
{
return GetMongo();
});
taskList.Add(t1);
taskList.Add(t2);
t1.Start();
t2.Start();
Task.WhenAll(taskList.ToArray()).ContinueWith(x =>
{
Console.WriteLine("任务执行完毕");
Console.WriteLine(x.Result[0]);
Console.WriteLine(x.Result[1]);
});
Console.ReadLine();
}
public static string GetName()
{
Thread.Sleep(5000);
return "MSSQL";
}
public static string GetMongo()
{
Thread.Sleep(10000);
return "MongoDB";
}
}
}
Task直接进行线程同步 Tasl.WaitAll() (相当于AutoResetEvent)