第七节:利用CancellationTokenSource实现任务取消和利用CancellationToken类检测取消异常。
一. 传统的线程取消
所谓的线程取消,就是线程正在执行的过程中取消线程任务。
传统的线程取消,是通过一个变量来控制,但是这种方式,在release模式下,被优化从cpu高速缓存中读取,而不是从内存中读取,会造成主线程无法执行这一个bug。
{
var isStop = false;
var thread = new Thread(() =>
{
while (!isStop)
{
Thread.Sleep();
Console.WriteLine("当前thread={0} 正在运行", Thread.CurrentThread.ManagedThreadId);
}
});
thread.Start();
Thread.Sleep();
isStop = true;
}

PS: 通过上面的代码看可以看出来,传统模式的线程取消,在排除release模式bug的情况下,局限性还是很明显的。比如:当子线程任务取消的那一刻,我想执行另外一项任务;我想延时取消一个线程任务;线程取消的时候抛异常。
上述这几种情况,我们都要借助单独的类来处理。
二. CancellationTokenSource实现任务取消
1. 取消任务的同时触发一个函数
利用Cancel方法、Register注册、source.Token标记取消位来实现。
{
CancellationTokenSource source = new CancellationTokenSource();
//注册一个线程取消后执行的逻辑
source.Token.Register(() =>
{
//这里执行线程被取消后的业务逻辑.
Console.WriteLine("-------------我是线程被取消后的业务逻辑---------------------");
});
Task.Run(() =>
{
while (!source.IsCancellationRequested)
{
Thread.Sleep();
Console.WriteLine("当前thread={0} 正在运行", Thread.CurrentThread.ManagedThreadId);
}
}, source.Token);
Thread.Sleep();
source.Cancel();
}

2. 延时取消
线程的延时取消有两种方式:
方案一:CancelAfter方法。
#region 方案一:CancelAfter方法
{
CancellationTokenSource source = new CancellationTokenSource();
//注册一个线程取消后执行的逻辑
source.Token.Register(() =>
{
//这里执行线程被取消后的业务逻辑.
Console.WriteLine("-------------我是线程被取消后的业务逻辑---------------------");
}); Task.Run(() =>
{
while (!source.IsCancellationRequested)
{
Thread.Sleep();
Console.WriteLine("当前thread={0} 正在运行", Thread.CurrentThread.ManagedThreadId);
}
}, source.Token); Thread.Sleep();
//4s后自动取消
source.CancelAfter(new TimeSpan(, , , ));
}
#endregion
方案二:CancellationTokenSource构造函数(不再需要Cancel方法了)。
{
//4s后自动取消
CancellationTokenSource source = new CancellationTokenSource();
//注册一个线程取消后执行的逻辑
source.Token.Register(() =>
{
//这里执行线程被取消后的业务逻辑.
Console.WriteLine("-------------我是线程被取消后的业务逻辑---------------------");
});
Task.Run(() =>
{
while (!source.IsCancellationRequested)
{
Thread.Sleep();
Console.WriteLine("当前thread={0} 正在运行", Thread.CurrentThread.ManagedThreadId);
}
}, source.Token);
Thread.Sleep();
}
3. 组合取消
利用CreateLinkedTokenSource构建CancellationTokenSource的组合体,其中任何一个体取消,则组合体就取消。
{
CancellationTokenSource source1 = new CancellationTokenSource();
//source1.Cancel();
CancellationTokenSource source2 = new CancellationTokenSource();
source2.Cancel();
var combineSource = CancellationTokenSource.CreateLinkedTokenSource(source1.Token, source2.Token);
Console.WriteLine("s1={0} s2={1} s3={2}", source1.IsCancellationRequested,
source2.IsCancellationRequested,
combineSource.IsCancellationRequested);
}
上述代码,source1和source2中的任何一个取消,combineSource就会被取消。

三. CancellationToken类监控取消
CancellationToken类下ThrowIfCancellationRequested属性,等价于if (XXX.IsCancellationRequested){throw new Exception("报错了");}
只要取消就报错。
{
CancellationTokenSource source1 = new CancellationTokenSource();
CancellationTokenSource source2 = new CancellationTokenSource();
var combineSource = CancellationTokenSource.CreateLinkedTokenSource(source1.Token, source2.Token);
source1.Cancel();
//if (combineSource.IsCancellationRequested)
//{
// throw new Exception("报错了");
//}
//等价于上面那句话
try
{
combineSource.Token.ThrowIfCancellationRequested();
}
catch (Exception)
{
Console.WriteLine("报错了");
}
Console.WriteLine("s1={0} s2={1} s3={2}", source1.IsCancellationRequested,
source2.IsCancellationRequested,
combineSource.IsCancellationRequested);
}

第七节:利用CancellationTokenSource实现任务取消和利用CancellationToken类检测取消异常。的更多相关文章
- centos Linux下磁盘管理 parted,df ,du,fdisk,partprobe,mkfs.ext4,mount,/etc/fstab,fsck,e2fsck,mk2efs,tmpfs ,nr_inodes, LVM,传统方式扩容文件系统 第七节课
centos Linux下磁盘管理 parted,df ,du,fdisk,partprobe,mkfs.ext4,mount,/etc/fstab,fsck,e2fsck,mk2efs,tmpf ...
- 基于Extjs的web表单设计器 第七节——取数公式设计之取数公式的使用
基于Extjs的web表单设计器 基于Extjs的web表单设计器 第一节 基于Extjs的web表单设计器 第二节——表单控件设计 基于Extjs的web表单设计器 第三节——控件拖放 基于Extj ...
- JAVA 从GC日志分析堆内存 第七节
JAVA 从GC日志分析堆内存 第七节 在上一章中,我们只设置了整个堆的内存大小.但是我们知道,堆又分为了新生代,年老代.他们之间的内存怎么分配呢?新生代又分为Eden和Survivor,他们的比 ...
- VUE2.0实现购物车和地址选配功能学习第七节
第七节 卡片选中,设置默认 1.卡片选中html:<li v-for="(item,index) in filterAddress" v-bind:class="{ ...
- delphi 线程教学第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行
第七节:在多个线程时空中,把各自的代码塞到一个指定的线程时空运行 以 Ado 为例,常见的方法是拖一个 AdoConnection 在窗口上(或 DataModule 中), 再配合 AdoQ ...
- J2EE进阶(七)利用SSH框架根据数据表建立model类
J2EE进阶(七)利用SSH框架根据数据表建立model类 前言 在利用SSH框架进行项目开发时,若将数据库已经建好,并且数据表之间的依赖关系已经确定,可以利用Hibernate的反转功能进行mode ...
- CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第七节
第七节:使用下一代CUDA硬件,快乐加速度 原文链接 Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个 ...
- 火云开发课堂 - 《使用Cocos2d-x 开发3D游戏》系列 第七节:PS基础:UV动画
<使用Cocos2d-x 开发3D游戏>系列在线课程 第七节:PS基础:UV动画 视频地址:http://edu.csdn.net/course/attend/1330/20807 交流论 ...
- ES6 第七节 ES6中新增的数组知识(1)
目录 ES6 第七节 ES6中新增的数组知识(1) 第七节 ES6中新增的数组知识(1) JSON数组格式转换 Array.of()方法: find()实例方法: ES6 第七节 ES6中新增的数组知 ...
随机推荐
- centos7.4系统升级kernel内核
在实验环境下,已安装了最新的CentOS 7.4操作系统,现在需要升级内核版本. 实验环境CentOS-7-x86_64-Minimal-1708.iso CentOS Linux release 7 ...
- Python基础——0前言
python虽然这几年才兴起,但是已经是一门“老”语言了. python的诞生历史也很有趣.Python的创始人为Guido van Rossum(龟叔).1989年圣诞节期间,在阿姆斯特丹,Guid ...
- Hive:ORC File Format存储格式详解
一.定义 ORC File,它的全名是Optimized Row Columnar (ORC) file,其实就是对RCFile做了一些优化. 据官方文档介绍,这种文件格式可以提供一种高效的方法来存储 ...
- day 12 装饰器
nonlocal关键字 # 作用:将 L 与 E(E中的名字需要提前定义) 的名字统一# 应用场景:如果想在被嵌套的函数中修改外部函数变量(名字)的值# 案例:def outer(): n ...
- [P1169] 棋盘制作 &悬线法学习笔记
学习笔记 悬线法 最大子矩阵问题: 在一个给定的矩形中有一些障碍点,找出内部不包含障碍点的,边与整个矩形平行或重合的最大子矩形. 极大子矩型:无法再向外拓展的有效子矩形 最大子矩型:最大的一个有效子矩 ...
- top 自动执行的shell脚本中,使用top -n 1 > log.txt, 上电自动执行,文件无输出
. 自动执行的shell脚本中,使用top -n > log.txt, 上电自动执行,文件无输出,使用一下命令解决: //usr/bin/top -d -n -b > log.txt 如果 ...
- 如何卸载VS 2017之前版本比如VS 2013、VS2015、 VS vNext?
前言 大学专业为软件工程,进入大学之后才知道这个专业需要用到笔记本,我的笔记本配置为I3,内存4个G,已经有大几年了,中间坏了修了一次一直用到现在,这个笔记本还是我哥打工过年回来身上仅有的三四千块钱所 ...
- Python变量的本质与intern机制
变量的存储 a = 'abc' 理解:①先在内存中生成一个字符串‘abc’ ②可以把比变量名a看做一个便利贴,然后将a贴到‘abc’中 ③注意顺序,是生成‘abc’,然后再创建a指向‘abc’ ...
- Reachability from the Capital CodeForces - 999E (强连通)
There are nn cities and mm roads in Berland. Each road connects a pair of cities. The roads in Berla ...
- css 通配符选择器
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...