创建Task
1.new方式实例化一个Task,需要通过Start方法启动
Task task = new Task(() =>
{
Thread.Sleep(100);
Console.WriteLine($"hello, task1的线程ID为{Thread.CurrentThread.ManagedThreadId}");
});
task.Start();
2.Task.Factory.StartNew(Action action)创建和启动一个Task
Task task2 = Task.Factory.StartNew(() =>
{
Thread.Sleep(100);
Console.WriteLine($"hello, task2的线程ID为{ Thread.CurrentThread.ManagedThreadId}");
});
3.Task.Run(Action action)将任务放在线程池队列,返回并启动一个Task
Task task3 = Task.Run(() =>
{
Thread.Sleep(100);
Console.WriteLine($"hello, task3的线程ID为{ Thread.CurrentThread.ManagedThreadId}");
});
task.Status
TaskStatus 枚举
Task对象的状态,可以查看当前task对象是在什么状态
task.Wait()
Task对象的Wait方法会阻塞主线程,不让主线程继续执行,等当前的task对象完成了才继续
Task.WaitAll()
task.Result
Task.Delay()
不要用Thread.Sleep();
,这个会阻塞当前线程,有可能是主线程。Task.Delay()
创建一个在指定时间后完成的Task。既然是Task,就可以用await等它完成。
用await等它完成,就相当于Thread.Sleep();的效果。但是await不会阻塞当前线程。
在webapi中高并发的场景中,要暂停时间,千万不能用Thread.Sleep();
,要用就用await Task.Delay()
Task
如果Task任务有返回值,返回类型就是Task的泛型类型。用Task对象的Result取返回类型的值
Task<string> task1 = new Task<string>(() =>
{
Thread.Sleep(1000);
return "哈哈哈";
});
task1.Start();
Console.WriteLine(task1.Result);
连续任务
如果一个任务的执行依赖于另一个任务,即任务的执行有先后顺序。此时,我们可以使用连续任务。
task.ContinueWith(ReadNews)表示一个任务task结束后,才开始执行另一个任务。
static void Main(string[] args)
{
Task t1 = new Task(() =>
{
Thread.Sleep(1000);
Console.WriteLine("哈哈哈");
});
Task t2 = t1.ContinueWith(A);
Task t3 = t2.ContinueWith(B);
t1.Start();
Console.ReadKey();
}
static void A(Task odj)
{
Thread.Sleep(1000);
Console.WriteLine("呵呵呵");
}
static void B(Task odj)
{
Thread.Sleep(1000);
Console.WriteLine("嘿嘿嘿");
}
//打印结果
//哈哈哈
//呵呵呵
//嘿嘿嘿
取消任务CancellationTokenSource
给Task传递一个CancellationToken
参数,
static void Main(string[] args) {
CancellationTokenSource tokenSource = new CancellationTokenSource();
tokenSource.CancelAfter(5000);//5秒钟后请求被取消
//还可以手动调用取消,当需要取消Task执行的时候,就手动调用这个
//tokenSource.Cancel();
Task task = testAsync2(tokenSource.Token);
Console.ReadLine();
}
static Task testAsync2(CancellationToken token) {
return Task.Run(() => {
int i = 0;
while (true) {
Console.WriteLine("执行......." + i++);
//需要在方法里面判断是不是被取消了,进行取消时的一些操作
if (token.IsCancellationRequested) {
Console.WriteLine("请求被取消");
break;
}
//如果执行到这一句,请求被取消了,直接抛出异常
token.ThrowIfCancellationRequested();
}
Console.WriteLine("完成");
});
}
在Async方法中,都可以传递一个
CancellationToken
参数进去,设置取消。防止这个异步方法超时什么的。
在WebAPI中,每个Action都可以带一个CancellationToken
参数。这参数,请求的时候不用传值。
当http请求被取消的,Action方法也跟着取消。尽量每个方法都传递一个这个值。
[HttpGet("cancel")]
public string cancel(CancellationToken toekn) {
int i =0;
while (true) {
Console.WriteLine("执行中...."+i++);
if (toekn.IsCancellationRequested) {
Console.WriteLine("请求已经取消");
toekn.ThrowIfCancellationRequested();
}
}
return "完成";
}