TPL异步并行编程之取消任务
TPL异步并行编程之简单使用
在上篇随笔里面说明了Task的使用,仅仅是简单使用,有时候把一个任务交给Task去执行,但是呢还是要管理下,比如说:我要叫这个任务停止了,不做了,任务取消了,或者超时了
在传统的While里面我们可以这样做,1 通过标识 2 通过一个方法抛异常,3 其他办法
举个例子:while(true){
if(isNotCancel){
//每次都判断下,取消没有,当然isNotCancel需要加上lock的
}
}
难道在Task里面有什么新奇吗?其实也没啥新奇的,那Task怎么取消呢?来点干货吧
一 轮训检测
直接调用task.cancel方法,但是下Task函数体内部必须做轮训检测是否被取消,且看代码
static void Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource(); CancellationToken token = tokenSource.Token; Task task=new Task(() =>
{
while (true)
{
if (token.IsCancellationRequested)
{
break;
}
else
{ }
}
},token); Console.WriteLine("运行"); task.Start(); Thread.Sleep(*); tokenSource.Cancel(); Console.ReadKey();
}
二 取消过程拦截检测
在调用task.cancel方法是会在真正改变token.IsCancellationRequested值之前,调用token中所注册的函数,也就是说token.cancel(),调用后会调用token.register所注册的方法,然后再更改token.IsCancellationRequested只为true,那么反过来在注册的方法中我们就可以检测是否调用了cancel方法了也就自然检测到了已经取消了
且看代码说话:
static void Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource(); CancellationToken token = tokenSource.Token; Task task=new Task(() =>
{
while (true)
{
if (token.IsCancellationRequested)
{
break;
}
else
{ }
}
},token); Console.WriteLine("运行"); token.Register(() =>
{
Console.WriteLine("取消了,在取消之前必定调用了我");
}); task.Start(); Thread.Sleep(*); tokenSource.Cancel(); Console.ReadKey();
}
三 使用信号量来检测是否取消
现在我们启用2个Task,TaskA,TaskB,TaskB需要TaskA取消后才能执行,那么我们也可以在TaskB中执行代码时检测TaskA已被取消了,且看代码
static void Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource(); CancellationToken token = tokenSource.Token; Task task=new Task(() =>
{
while (true)
{
// 一直在运行,下面那个家伙得等着我被取消或者把事情做完
if (token.IsCancellationRequested)
{
//我已被取消该时候退出了
break;
}
}
},token); Task.Run(() =>
{
//我一开始就被上面那个task家伙挂起了,我需要他取消我才能干活~~
token.WaitHandle.WaitOne();
while (true)
{
// 开始干活
}
}); task.Start(); Thread.Sleep(*); tokenSource.Cancel(); Console.ReadKey();
}
四 多个协作的Task一个取消则其他Task也被取消,这样也可以取消一组Task
就好比我们几个人一起干一件事情,但是这件事情需要每个分工的相互协作才能继续,比如玉女双休剑,需要2人同时练功才行,其中一个人说我不行了 那都不行了,且看代码
4.1 共用一个Token
static void Main(string[] args)
{
CancellationTokenSource tokenSource = new CancellationTokenSource(); // create the cancellation token
CancellationToken token = tokenSource.Token; // create the tasks
Task task1 = new Task(() =>
{
for (int i = ; i < int.MaxValue; i++)
{
token.ThrowIfCancellationRequested();
Console.WriteLine("Task 1 - Int value {0}", i);
}
}, token); Task task2 = new Task(() =>
{
for (int i = ; i < int.MaxValue; i++)
{
token.ThrowIfCancellationRequested();
Console.WriteLine("Task 2 - Int value {0}", i);
}
}, token);
// wait for input before we start the tasks
Console.WriteLine("Press enter to start tasks");
Console.WriteLine("Press enter again to cancel tasks");
Console.ReadLine(); // start the tasks
task1.Start();
task2.Start(); // read a line from the console.
Console.ReadLine(); // cancel the task
Console.WriteLine("Cancelling tasks");
tokenSource.Cancel();
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
4.2 Token组
static void Main(string[] args)
{
// create the cancellation token sources
CancellationTokenSource tokenSource1 = new CancellationTokenSource();
CancellationTokenSource tokenSource2 = new CancellationTokenSource();
CancellationTokenSource tokenSource3 = new CancellationTokenSource(); // create a composite token source using multiple tokens
CancellationTokenSource compositeSource =
CancellationTokenSource.CreateLinkedTokenSource(
tokenSource1.Token, tokenSource2.Token, tokenSource3.Token); // create a cancellable task using the composite token
Task task = new Task(() =>
{
// wait until the token has been cancelled
compositeSource.Token.WaitHandle.WaitOne();
// throw a cancellation exception
throw new OperationCanceledException(compositeSource.Token);
}, compositeSource.Token); // start the task
task.Start(); // cancel one of the original tokens
Thread.Sleep(*);
tokenSource2.Cancel(); // wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
五 抛出异常
ThrowIfCancellationRequested,在四中已经看到如果调用cancel方法会处罚ThrowIfCancellationRequested函数的执行,那么相应的Task检测到异常如果不做任何处理的情况下也就退出了,且看代码
代码 Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> static void Main(string[] args)
{
// create the cancellation token source
CancellationTokenSource tokenSource1 = new CancellationTokenSource(); // create the cancellation token
CancellationToken token1 = tokenSource1.Token; // create the first task, which we will let run fully
Task task1 = new Task(() =>
{
for (int i = ; i < ; i++)
{
token1.ThrowIfCancellationRequested();
Console.WriteLine("Task 1 - Int value {0}", i);
}
}, token1); // create the second cancellation token source
CancellationTokenSource tokenSource2 = new CancellationTokenSource(); // create the cancellation token
CancellationToken token2 = tokenSource2.Token; // create the second task, which we will cancel
Task task2 = new Task(() =>
{
for (int i = ; i < int.MaxValue; i++)
{
token2.ThrowIfCancellationRequested();
Console.WriteLine("Task 2 - Int value {0}", i);
}
}, token2); // start all of the tasks
task1.Start();
task2.Start(); // cancel the second token source
tokenSource2.Cancel();
// write out the cancellation detail of each task
Console.WriteLine("Task 1 cancelled? {0}", task1.IsCanceled);
Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled);
// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();
}
最后
其实取消Task的执行还有其他办法,也可以自己实现不一定就要TPL通过的api来实现
TPL异步并行编程之取消任务的更多相关文章
- TPL异步并行编程之简单使用
并行编程一直是一个老生常谈的话题 在这里记录一下TPL编程,这在net4.0 微软就已经提供了多核时代下的并行库,其中最核心的最常用的也就是Task 一 Task是什么 Task可以简单的理解为一个线 ...
- TPL异步并行编程之回调
Task是基于ThreadPool线程池基础上的高度异步多线程编程,如果有一天我希望一个需要长时间运行的Task,在被某些异常终止后还能回调一些代码就可以知道Task终止的原因了吧 是的,且看代码 p ...
- TPL异步并行编程之任务超时
此处参考自阿涛的博文:http://www.cnblogs.com/HelloMyWorld/p/5526914.html 一 自己定义 基本的思路: net中异步操作由于是交给线程来实现,因此不可能 ...
- Task C# 多线程和异步模型 TPL模型 【C#】43. TPL基础——Task初步 22 C# 第十八章 TPL 并行编程 TPL 和传统 .NET 异步编程一 Task.Delay() 和 Thread.Sleep() 区别
Task C# 多线程和异步模型 TPL模型 Task,异步,多线程简单总结 1,如何把一个异步封装为Task异步 Task.Factory.FromAsync 对老的一些异步模型封装为Task ...
- C# 异步编程3 TPL Task 异步程序开发
.Net在Framework4.0中增加了任务并行库,对开发人员来说利用多核多线程CPU环境变得更加简单,TPL正符合我们本系列的技术需求.因TPL涉及内容较多,且本系列文章为异步程序开发,所以本文并 ...
- .NET Framework各版本比较
(1)本文比较了.NET Framework多个版本之间的区别,方便各位选择和切换.NET Framework. 版本号 发布日期 Visual Studio的版本 Windows上的默认情况 CLR ...
- WinForm调用钉钉获取考勤结果
关注点: 1.钉钉AccessToken的获取和防止过期 2.使用TPL并行编程调用钉钉接口 需求详解 公司前台有个大屏,领导想显示全部员工的考勤结果统计情况和车间的实时监控视频,还有车间的看板.简单 ...
- System.Threading.Tasks
前言: 我们之前介绍了两种构建多线程软件的编程技术(使用异步委托或通过System.Threading的成员).这两个可以在任何版本的.NET平台工作. 关于System.Threading 的介绍 ...
- 使用JAVA CompletableFuture实现流水线化的并行处理,深度实践总结
大家好,又见面啦. 在项目开发中,后端服务对外提供API接口一般都会关注响应时长.但是某些情况下,由于业务规划逻辑的原因,我们的接口可能会是一个聚合信息处理类的处理逻辑,比如我们从多个不同的地方获取数 ...
随机推荐
- atlas z 轴
问题源自一个帖子,因为上传的图比较多,就另开了这个贴写下自己的试验结果,原帖在下面链接中 http://game.ceeger.com/forum/read.php?tid=8911#info NGU ...
- Tri_integral Summer Training 8 总结
比赛链接 题目 B C E F G I 这是孟加拉国的区域赛. 开场ss读懂了c发现是个水题,于是去敲,结果手贱wa了一炮,不过很快就修正了错误.B题过了不少,我去读,发现是个水题,意识让Moor敲. ...
- 基于visual Studio2013解决算法导论之023队列实现(基于数组)
题目 基于数组的队列 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <time.h> #i ...
- 基于visual Studio2013解决算法导论之021单向循环链表
题目 单向循环链表的操作 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <time.h> ...
- 【转】关于C语言生成不重复的随机数
一 说起随机函数,恐怕又有人说这是老生长谈了……一般很多人都形成了自己的固定格式,因为随机数用处比较大,用的时候比较多,拿过来就用了.但是新手不这么 干,他们总是抱有疑惑,我就是一个新手,而且较菜…… ...
- Office 365 - SharePoint 2013 Online之加入App开发工具Napa
1.新建一个站点集,模板选择开发者模板.例如以下图: 2.确定以后,须要稍等一会儿; 3.点击站点内容,加入app,例如以下图: 4.进入SharePoint Store.选择Napa.例如以下图: ...
- BZOJ 4145: [AMPPZ2014]The Prices( 状压dp + 01背包 )
我自己只能想出O( n*3^m )的做法....肯定会T O( nm*2^m )做法: dp( x, s ) 表示考虑了前 x 个商店, 已买的东西的集合为s. 考虑转移 : 先假设我们到第x个商店去 ...
- HDU--杭电--1501--Zipper--深搜、DP都好
Zipper Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- [转]CentOS_yum的详细使用方法
yum 是什么yum = Yellow dog Updater, Modified主要功能是更方便的添加/删除/更新RPM包.它能自动解决包的倚赖性问题.它能便于管理大量系统的更新问题 yum特点可以 ...
- MFC 之 截图工具
这个截图工具能实现最主要的截图功能,并保存为bmp图片. 编写环境是vs2005,使用Unicode,基于对话框. 没什么难度,直接看代码 项目名称为CutOut // CutOutDlg.h : 头 ...