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接口一般都会关注响应时长.但是某些情况下,由于业务规划逻辑的原因,我们的接口可能会是一个聚合信息处理类的处理逻辑,比如我们从多个不同的地方获取数 ...
随机推荐
- VC++在对话框中加入属性页
当一个基于对话框的程序中有相当多的控件时,你一定会想到使用属性页来将这些控件分类放置.本文针对这种方法来讨论几种可能实现的方案. 方案一本方案的例子请见源代码打包文件中的Property1部分 在对话 ...
- HDU 4739 求正方形个数
九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/11711707 求所有可能围成的正方形,借个代码 #include <que ...
- Android 属性动画 源码解析 深入了解其内部实现
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42056859,本文出自:[张鸿洋的博客] 我参加了博客之星评选,如果你喜欢我的博 ...
- linux查看端口和进程
查看进程 ps -aux | grep appname 杀死进程 kill pid 查看端口: netstat -ap | grep 端口号 netstat -ap | grep 进程名字 lsof ...
- [置顶] java的foreach循环
foreach语句是java5之后的新特征之一,在循环遍历数组.集合方面更加简洁. 使用foreach循环遍历数组和集合时,无需获得数组和集合的长度,无须根据索引来访问数组元素和集合元素,foreac ...
- structure and interpretation of Computer programs -- Foreword
Foreword 前言 Educators, generals, dieticians, psychologists, and parents program. Armies, students ...
- 基于visual Studio2013解决算法导论之004随机排列数组
题目 随机排列数组 解决代码及点评 #include <stdio.h> #include <stdlib.h> #include <malloc.h> # ...
- C#Windows的HelloWorld
在MSDN中找到Form类:MSDN-->.NET开发-->.NET Framework SDK 2.0-->Class Library Reference -->System ...
- mysql服务无法启动
可能是没有data文件夹,可以新建或拷贝以前的data文件夹到安装目录.
- 130825组队赛-Regionals 2012, North America - East Central NA
A.Babs' Box Boutique 一道简单的dfs搜索题,需要两两比较,然后搜到底,得到最大值就行了.比赛时队友写的,我只负责debug..赛后自己写的.. #include<iostr ...