第七节:利用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中新增的数组知 ...
随机推荐
- jQuery根据radio来控制texteara
最近遇到一个问题:需要通过点击radio来控制texteara的属性变化. 这里主要有两个知识点:1,给texteara设置属性:2,给texteara设置背景颜色. 在这里,假设texteara的i ...
- Vue学习之路2-项目初搭建
1.检查环境是否全部安装成功 2.创建项目 2.1.打开dos命令窗口,使用dos命令转到项目文件夹下: 2.2.输入创建项目命令:vue init webpack myproject1 创建不同的打 ...
- LeetCode算法题-Repeated Substring Pattern(Java实现)
这是悦乐书的第236次更新,第249篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第103题(顺位题号是459).给定非空字符串检查是否可以通过获取它的子字符串并将子字符 ...
- spring注解驱动--组件注册
为容器中注册Bean @Configuration代表该类是一个配置类,配置类起到的作用和xml配置文件一样 @Bean代表该方法的返回对象作为Bean加入IOC容器,默认Bean的id是方法的名称. ...
- MSIL学习------从HelloWorld开始
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3889z1y72b28 ...
- tcping ,一个好用的TCP端口检测工具
1.常用的用法(windows) tcp -w 10 -t -d -i 5 -j --color 81.156.165.66 443 2. http模式 -u,与-h命令连用,每一行输出目标的url ...
- js 对数据进行过滤
//对数据进行过滤 Array.prototype.filter = Array.prototype.filter || function (func) { var arr = this; var r ...
- Java 208 道面试题:第一模块答案
目前市面上的面试题存在两大问题:第一,题目太旧好久没有更新了,还都停留在 2010 年之前的状态:第二,近几年 JDK 更新和发布都很快,Java 的用法也变了不少,加上 Java 技术栈也加入了很多 ...
- 分治FFT的三种含义
分治FFT是几个算法的统称.它们之间并无关联. 分治多项式乘法 问题如求\(\prod_{i=1}^na_ix+b\). 若挨个乘复杂度为\(O(n^2\log n)\),可分治做这件事,复杂度为\( ...
- python和anacoda安装第三方库的位置
查看已安装库及版本号,命令行pip list 安装第三方库位置: