创建Task

1.new方式实例化一个Task,需要通过Start方法启动

  1. Task task = new Task(() =>
  2. {
  3. Thread.Sleep(100);
  4. Console.WriteLine($"hello, task1的线程ID为{Thread.CurrentThread.ManagedThreadId}");
  5. });
  6. task.Start();

2.Task.Factory.StartNew(Action action)创建和启动一个Task

  1. Task task2 = Task.Factory.StartNew(() =>
  2. {
  3. Thread.Sleep(100);
  4. Console.WriteLine($"hello, task2的线程ID为{ Thread.CurrentThread.ManagedThreadId}");
  5. });

3.Task.Run(Action action)将任务放在线程池队列,返回并启动一个Task

  1. Task task3 = Task.Run(() =>
  2. {
  3. Thread.Sleep(100);
  4. Console.WriteLine($"hello, task3的线程ID为{ Thread.CurrentThread.ManagedThreadId}");
  5. });

task.Status

TaskStatus 枚举
Task对象的状态,可以查看当前task对象是在什么状态

task.Wait()

Task对象的Wait方法会阻塞主线程,不让主线程继续执行,等当前的task对象完成了才继续

Task.WaitAll()

传入参数,task对象。等待这些task全部执行完成。

task.Result

等待task拿到结果,尽量不要用,会阻塞主线程。

Task.Delay()

不要用Thread.Sleep();,这个会阻塞当前线程,有可能是主线程。
Task.Delay()创建一个在指定时间后完成的Task。既然是Task,就可以用await等它完成。
用await等它完成,就相当于Thread.Sleep();的效果。但是await不会阻塞当前线程。
在webapi中高并发的场景中,要暂停时间,千万不能用Thread.Sleep();,要用就用await Task.Delay()

Task

如果Task任务有返回值,返回类型就是Task的泛型类型。用Task对象的Result取返回类型的值

  1. Task<string> task1 = new Task<string>(() =>
  2. {
  3. Thread.Sleep(1000);
  4. return "哈哈哈";
  5. });
  6. task1.Start();
  7. Console.WriteLine(task1.Result);

连续任务

如果一个任务的执行依赖于另一个任务,即任务的执行有先后顺序。此时,我们可以使用连续任务。
task.ContinueWith(ReadNews)表示一个任务task结束后,才开始执行另一个任务。

  1. static void Main(string[] args)
  2. {
  3. Task t1 = new Task(() =>
  4. {
  5. Thread.Sleep(1000);
  6. Console.WriteLine("哈哈哈");
  7. });
  8. Task t2 = t1.ContinueWith(A);
  9. Task t3 = t2.ContinueWith(B);
  10. t1.Start();
  11. Console.ReadKey();
  12. }
  13. static void A(Task odj)
  14. {
  15. Thread.Sleep(1000);
  16. Console.WriteLine("呵呵呵");
  17. }
  18. static void B(Task odj)
  19. {
  20. Thread.Sleep(1000);
  21. Console.WriteLine("嘿嘿嘿");
  22. }
  23. //打印结果
  24. //哈哈哈
  25. //呵呵呵
  26. //嘿嘿嘿

取消任务CancellationTokenSource

给Task传递一个CancellationToken参数,

  1. static void Main(string[] args) {
  2. CancellationTokenSource tokenSource = new CancellationTokenSource();
  3. tokenSource.CancelAfter(5000);//5秒钟后请求被取消
  4. //还可以手动调用取消,当需要取消Task执行的时候,就手动调用这个
  5. //tokenSource.Cancel();
  6. Task task = testAsync2(tokenSource.Token);
  7. Console.ReadLine();
  8. }
  9. static Task testAsync2(CancellationToken token) {
  10. return Task.Run(() => {
  11. int i = 0;
  12. while (true) {
  13. Console.WriteLine("执行......." + i++);
  14. //需要在方法里面判断是不是被取消了,进行取消时的一些操作
  15. if (token.IsCancellationRequested) {
  16. Console.WriteLine("请求被取消");
  17. break;
  18. }
  19. //如果执行到这一句,请求被取消了,直接抛出异常
  20. token.ThrowIfCancellationRequested();
  21. }
  22. Console.WriteLine("完成");
  23. });
  24. }

在Async方法中,都可以传递一个CancellationToken参数进去,设置取消。防止这个异步方法超时什么的。

在WebAPI中,每个Action都可以带一个CancellationToken参数。这参数,请求的时候不用传值。
当http请求被取消的,Action方法也跟着取消。尽量每个方法都传递一个这个值。

  1. [HttpGet("cancel")]
  2. public string cancel(CancellationToken toekn) {
  3. int i =0;
  4. while (true) {
  5. Console.WriteLine("执行中...."+i++);
  6. if (toekn.IsCancellationRequested) {
  7. Console.WriteLine("请求已经取消");
  8. toekn.ThrowIfCancellationRequested();
  9. }
  10. }
  11. return "完成";
  12. }