TPL异步并行编程之取消任务

TPL异步并行编程之简单使用

在上篇随笔里面说明了Task的使用,仅仅是简单使用,有时候把一个任务交给Task去执行,但是呢还是要管理下,比如说:我要叫这个任务停止了,不做了,任务取消了,或者超时了

在传统的While里面我们可以这样做,1 通过标识 2 通过一个方法抛异常,3 其他办法

举个例子:while(true){

  if(isNotCancel){

    //每次都判断下,取消没有,当然isNotCancel需要加上lock的

  }

}

难道在Task里面有什么新奇吗?其实也没啥新奇的,那Task怎么取消呢?来点干货吧

一 轮训检测

直接调用task.cancel方法,但是下Task函数体内部必须做轮训检测是否被取消,且看代码

 1 static void Main(string[] args)
 2         {
 3             CancellationTokenSource tokenSource = new CancellationTokenSource();
 4
 5             CancellationToken token = tokenSource.Token;
 6
 7             Task task=new Task(() =>
 8             {
 9                 while (true)
10                 {
11                     if (token.IsCancellationRequested)
12                     {
13                         break;
14                     }
15                     else
16                     {
17
18                     }
19                 }
20             },token);
21
22
23             Console.WriteLine("运行");
24
25
26
27             task.Start();
28
29             Thread.Sleep(5*1000);
30
31             tokenSource.Cancel();
32
33             Console.ReadKey();
34         }

二  取消过程拦截检测

在调用task.cancel方法是会在真正改变token.IsCancellationRequested值之前,调用token中所注册的函数,也就是说token.cancel(),调用后会调用token.register所注册的方法,然后再更改token.IsCancellationRequested只为true,那么反过来在注册的方法中我们就可以检测是否调用了cancel方法了也就自然检测到了已经取消了

且看代码说话:

 1 static void Main(string[] args)
 2         {
 3             CancellationTokenSource tokenSource = new CancellationTokenSource();
 4
 5             CancellationToken token = tokenSource.Token;
 6
 7             Task task=new Task(() =>
 8             {
 9                 while (true)
10                 {
11                     if (token.IsCancellationRequested)
12                     {
13                         break;
14                     }
15                     else
16                     {
17
18                     }
19                 }
20             },token);
21
22
23             Console.WriteLine("运行");
24
25             token.Register(() =>
26             {
27                 Console.WriteLine("取消了,在取消之前必定调用了我");
28             });
29
30             task.Start();
31
32             Thread.Sleep(5*1000);
33
34             tokenSource.Cancel();
35
36             Console.ReadKey();
37         }

三 使用信号量来检测是否取消

现在我们启用2个Task,TaskA,TaskB,TaskB需要TaskA取消后才能执行,那么我们也可以在TaskB中执行代码时检测TaskA已被取消了,且看代码

 1 static void Main(string[] args)
 2         {
 3             CancellationTokenSource tokenSource = new CancellationTokenSource();
 4
 5             CancellationToken token = tokenSource.Token;
 6
 7             Task task=new Task(() =>
 8             {
 9                 while (true)
10                 {
11                     // 一直在运行,下面那个家伙得等着我被取消或者把事情做完
12                     if (token.IsCancellationRequested)
13                     {
14                         //我已被取消该时候退出了
15                         break;
16                     }
17                 }
18             },token);
19
20
21             Task.Run(() =>
22             {
23                 //我一开始就被上面那个task家伙挂起了,我需要他取消我才能干活~~
24                 token.WaitHandle.WaitOne();
25                 while (true)
26                 {
27                     // 开始干活
28                 }
29             });
30
31             task.Start();
32
33             Thread.Sleep(5*1000);
34
35             tokenSource.Cancel();
36
37             Console.ReadKey();
38         }

四 多个协作的Task一个取消则其他Task也被取消,这样也可以取消一组Task

就好比我们几个人一起干一件事情,但是这件事情需要每个分工的相互协作才能继续,比如玉女双休剑,需要2人同时练功才行,其中一个人说我不行了 那都不行了,且看代码

4.1 共用一个Token

 1 static void Main(string[] args)
 2         {
 3             CancellationTokenSource tokenSource = new CancellationTokenSource();
 4
 5             // create the cancellation token
 6             CancellationToken token = tokenSource.Token;
 7
 8             // create the tasks
 9             Task task1 = new Task(() =>
10             {
11                 for (int i = 0; i < int.MaxValue; i++)
12                 {
13                     token.ThrowIfCancellationRequested();
14                     Console.WriteLine("Task 1 - Int value {0}", i);
15                 }
16             }, token);
17
18             Task task2 = new Task(() =>
19             {
20                 for (int i = 0; i < int.MaxValue; i++)
21                 {
22                     token.ThrowIfCancellationRequested();
23                     Console.WriteLine("Task 2 - Int value {0}", i);
24                 }
25             }, token);
26             // wait for input before we start the tasks
27             Console.WriteLine("Press enter to start tasks");
28             Console.WriteLine("Press enter again to cancel tasks");
29             Console.ReadLine();
30
31             // start the tasks
32             task1.Start();
33             task2.Start();
34
35             // read a line from the console.
36             Console.ReadLine();
37
38             // cancel the task
39             Console.WriteLine("Cancelling tasks");
40             tokenSource.Cancel();
41             // wait for input before exiting
42             Console.WriteLine("Main method complete. Press enter to finish.");
43             Console.ReadLine();
44         }

4.2 Token组

 1 static void Main(string[] args)
 2         {
 3             // create the cancellation token sources
 4             CancellationTokenSource tokenSource1 = new CancellationTokenSource();
 5             CancellationTokenSource tokenSource2 = new CancellationTokenSource();
 6             CancellationTokenSource tokenSource3 = new CancellationTokenSource();
 7
 8             // create a composite token source using multiple tokens
 9             CancellationTokenSource compositeSource =
10                 CancellationTokenSource.CreateLinkedTokenSource(
11             tokenSource1.Token, tokenSource2.Token, tokenSource3.Token);
12
13             // create a cancellable task using the composite token
14             Task task = new Task(() =>
15             {
16                 // wait until the token has been cancelled
17                 compositeSource.Token.WaitHandle.WaitOne();
18                 // throw a cancellation exception
19                 throw new OperationCanceledException(compositeSource.Token);
20             }, compositeSource.Token);
21
22             // start the task
23             task.Start();
24
25             // cancel one of the original tokens
26             Thread.Sleep(2*1000);
27             tokenSource2.Cancel();
28
29             // wait for input before exiting
30             Console.WriteLine("Main method complete. Press enter to finish.");
31             Console.ReadLine();
32         }

五 抛出异常

ThrowIfCancellationRequested,在四中已经看到如果调用cancel方法会处罚ThrowIfCancellationRequested函数的执行,那么相应的Task检测到异常如果不做任何处理的情况下也就退出了,且看代码

 1 代码
 2
 3 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->        static void Main(string[] args)
 4         {
 5             // create the cancellation token source
 6             CancellationTokenSource tokenSource1 = new CancellationTokenSource();
 7
 8             // create the cancellation token
 9             CancellationToken token1 = tokenSource1.Token;
10
11             // create the first task, which we will let run fully
12             Task task1 = new Task(() =>
13             {
14                 for (int i = 0; i < 10; i++)
15                 {
16                     token1.ThrowIfCancellationRequested();
17                     Console.WriteLine("Task 1 - Int value {0}", i);
18                 }
19             }, token1);
20
21             // create the second cancellation token source
22             CancellationTokenSource tokenSource2 = new CancellationTokenSource();
23
24             // create the cancellation token
25             CancellationToken token2 = tokenSource2.Token;
26
27             // create the second task, which we will cancel
28             Task task2 = new Task(() =>
29             {
30                 for (int i = 0; i < int.MaxValue; i++)
31                 {
32                     token2.ThrowIfCancellationRequested();
33                     Console.WriteLine("Task 2 - Int value {0}", i);
34                 }
35             }, token2);
36
37             // start all of the tasks
38             task1.Start();
39             task2.Start();
40
41             // cancel the second token source
42             tokenSource2.Cancel();
43             // write out the cancellation detail of each task
44             Console.WriteLine("Task 1 cancelled? {0}", task1.IsCanceled);
45             Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled);
46             // wait for input before exiting
47             Console.WriteLine("Main method complete. Press enter to finish.");
48             Console.ReadLine();
49         }

最后

其实取消Task的执行还有其他办法,也可以自己实现不一定就要TPL通过的api来实现

时间: 2024-11-05 14:55:47

TPL异步并行编程之取消任务的相关文章

TPL异步并行编程之简单使用

并行编程一直是一个老生常谈的话题 在这里记录一下TPL编程,这在net4.0 微软就已经提供了多核时代下的并行库,其中最核心的最常用的也就是Task 一 Task是什么 Task可以简单的理解为一个线程的封装,向外部暴露几种接口,如常见的Task.Run,Task.Factory.StartNew:当一个Task启动后应用程序将会等待这个Task的执行,但是不会去阻塞UI线程,换句话说,我丢了一个任务跟一个线程并让他去执行,然后我马上回到UI线程,这个线程运行完了就告诉UI线程我完事了,然后继续

TPL异步并行编程之回调

Task是基于ThreadPool线程池基础上的高度异步多线程编程,如果有一天我希望一个需要长时间运行的Task,在被某些异常终止后还能回调一些代码就可以知道Task终止的原因了吧 是的,且看代码 public static Task AsyncRun(this ILoggerProvider logProvider, Action task, TaskCreationOptions taskOption, Action<Exception> exceptionHandler) { retur

TPL异步并行编程之任务超时

此处参考自阿涛的博文:http://www.cnblogs.com/HelloMyWorld/p/5526914.html 基本的思路: net中异步操作由于是交给线程来实现,因此不可能真正想js那样将一个单线程上的任务移除:如 var id=setTimeout(fun,200); if(id>0){ clearTimeout(id);//将一个任务从单线程的任务栈中移除,自然就做到了真正的移除任务 } 但是在net中一个任务交给线程执行后,具体什么时候执行完成我们并不确定,就算是我们把线程终

WinForm调用钉钉获取考勤结果

原文:WinForm调用钉钉获取考勤结果 关注点: 1.钉钉AccessToken的获取和防止过期 2.使用TPL并行编程调用钉钉接口 需求详解 公司前台有个大屏,领导想显示全部员工的考勤结果统计情况和车间的实时监控视频,还有车间的看板.简单说就是把大屏分割成几个区域.现在遇到的难题是钉钉获取考勤结果的api是只有明细记录,比如你公司1000人,那么可能回给你2000条考勤结果.分别是上班考勤和下班考勤的.没有整个公司的,我就需要这么一条数据就行了.但人家没有这样的接口提供.卷起袖子,干! 趟坑

NET中的并行编程(TPL)——多线程、异步、任务和并行计算

https://masuit.com/1201 谈一谈.NET中的并行编程(TPL)——多线程.异步.任务和并行计算 懒得勤快 发表于2018-04-26 19:41:00 | 最后修改于2018-06-27 23:44:40 .NET 多线程 异步 高并发 分类:.NET开发技术 | 评论总数:0条 | 热度:2243℃ 我要编辑 写在前面: 在做了几个月的高并发项目的过程中,其实发现自己真的提升了不少,所以也想把这段时间的收获分享给大家,然后写这篇文章发现,写下来是一发不可收拾,所以这篇文章

并行编程中的取消任务、共享状态,等等

在面对相互独立的数据或者相互独立的任务时,也许正是Parallel登场的时候. 比如说有一个盒子的集合,分别让盒子旋转一定的角度. void RotateBox(IEnumerable<Box> boxes, float degree) { Parallel.ForEach(boxes, box => box.Rotate(degree)); } 如果并行任务中的一个任务出现异常,需要结束出问题的任务呢? Parallel.ForEach为我们提供了一个重载方法,可以控制任务是否继续.

[翻译]在 .NET Core 中的并发编程

原文地址:http://www.dotnetcurry.com/dotnet/1360/concurrent-programming-dotnet-core 今天我们购买的每台电脑都有一个多核心的 CPU,允许它并行执行多个指令.操作系统通过将进程调度到不同的内核来发挥这个结构的优点.然而,还可以通过异步 I/O 操作和并行处理来帮助我们提高单个应用程序的性能.在.NET Core中,任务 (tasks) 是并发编程的主要抽象表述,但还有其他支撑类可以使我们的工作更容易. 并发编程 - 异步 v

异步编程和线程的使用(.NET 4.5 )

C#:异步编程和线程的使用(.NET 4.5 ) 异步编程和线程处理是并发或并行编程非常重要的功能特征.为了实现异步编程,可使用线程也可以不用.将异步与线程同时讲,将有助于我们更好的理解它们的特征. 本文中涉及关键知识点 1. 异步编程 2. 线程的使用 3. 基于任务的异步模式 4. 并行编程 5. 总结 异步编程 什么是异步操作?异步操作是指某些操作能够独立运行,不依赖主流程或主其他处理流程.通常情况下,C#程序从Main方法开始,当Main方法返回时结束.所有的操作都是按顺序执行的.执行操

使用异步编程

转发至:http://www.ituring.com.cn/article/130823 导言 现代的应用程序面临着诸多的挑战,如何构建具有可伸缩性和高性能的应用成为越来越多软件开发者思考的问题.随着应用规模的不断增大,业务复杂性的增长以及实时处理需求的增加,开发者不断尝试榨取硬件资源.优化. 在不断的探索中,出现了很多简化场景的工具,比如提供可伸缩计算资源的Amazon S3.Windows Azure,针对大数据的数据挖掘工具MapReduce,各种CDN服务,云存储服务等等.还有很多的工程