[No000017E]改善C#程序的建议7:正确停止线程
开发者总尝试对自己的代码有更多的控制。“让那个还在工作的线程马上停止下来”就是诸多要求中的一种。然而事与愿违,这里面至少存在两个问题:
第一个问题是:正如线程不能立即启动一样,线程也并不能说停就停。无论采用何种方式通知工作线程需要停止,工作线程都会忙完手头最紧要的活,然后在它觉得合适的时候退出。以最传统的Thread.Abort方法为例,如果线程当前正在执行的是一段非托管代码,那么CLR就不会抛出ThreadAbortException,只有当代码继续回到CLR中时,才会引发ThreadAbortException。当然,即便是在CLR环境中,ThreadAbortException也不会立即引发。
其次,正确停止线程,不在于调用者采取了什么行为(如最开始的Thread.Abort()方法),而更多依赖于工作线程是否能主动响应调用者的停止请求。大体机制是,如果线程需要被停止,那么线程自身就得负责开放给调用者这样的接口:Cancled,然后线程在工作的同时,还得以某种频率检测Cancled标识,若检测到Cancled,线程自己负责退出。
FCL现在为我们提供了标准的取消模式:协作式取消(Cooperative Cancellation)。协作式取消的机制就是上文提到的机制。下面是一个最基础的协作式取消的样例:
CancellationTokenSource cts = new CancellationTokenSource();
Thread t
=
new
Thread(()
=> { while
(
true
)
{ if
(cts.Token.IsCancellationRequested)
{
Console.WriteLine(
"
线程被终止!
"
); break
;
}
Console.WriteLine(DateTime.Now.ToString());
Thread.Sleep(
1000
);
}
});
t.Start();
Console.ReadLine();
cts.Cancel();
调用者使用CancellationTokenSource的Cancle方法通知工作线程退出。工作线程则以大致1000毫秒的频率一边工作,一边检查是否有外界传入进来的Cancel信号。若有这样的信号,则负责退出。可以看到,在正确停止线程的机制中,真正起到主要作用的是线程本身。样例中的工作代码比较简单,不过也足以说明问题。更复杂的计算式的工作,也应该以这样的一种方式,妥善而正确地处理退出。
协作式取消中的关键类型是CancellationTokenSource。它有一个关键属性Token,Token是一个名为CancellationToken的值类型。CancellationToken继而进一步提供了布尔值的属性IsCancellationRequested作为需要取消工作的标识。CancellationToken还有一个方法尤其值得注意,那就是Register方法。它负责传递一个Action委托,在线程停止的时候被回调,使用方法如:
cts.Token.Register(()
=> {
Console.WriteLine(
"
工作线程被终止了。
"
);
});
本建议中的例子使用Thread进行了演示,使用ThreadPool也是一样的模式,这里就不再赘述。后面我们还会讲到任务Task,它依赖于CancellationTokenSource和CancellationToken完成了所有的取消控制。
[No000017E]改善C#程序的建议7:正确停止线程的更多相关文章
- 改善C#程序的建议6:在线程同步中使用信号量
原文:改善C#程序的建议6:在线程同步中使用信号量 所谓线程同步,就是多个线程之间在某个对象上执行等待(也可理解为锁定该对象),直到该对象被解除锁定.C#中对象的类型分为引用类型和值类型.CLR在这两 ...
- [No000017D]改善C#程序的建议6:在线程同步中使用信号量
所谓线程同步,就是多个线程之间在某个对象上执行等待(也可理解为锁定该对象),直到该对象被解除锁定.C#中对象的类型分为引用类型和值类型.CLR在这两种类型上的等待是不一样的.我们可以简单的理解为在CL ...
- 改善C#程序的建议7:正确停止线程
原文:改善C#程序的建议7:正确停止线程 开发者总尝试对自己的代码有更多的控制.“让那个还在工作的线程马上停止下来”就是诸多要求中的一种.然而事与愿违,这里面至少存在两个问题: 第一个问题是:正如线程 ...
- 改善C#程序的建议10:用Parallel简化Task
在命名空间System.Threading.Tasks下,有一个静态类Parallel简化了在同步状态下的Task的操作.Parallel主要提供了3个有用的方法:For.ForEach.Invoke ...
- 改善C#程序的建议8:避免锁定不恰当的同步对象
原文:改善C#程序的建议8:避免锁定不恰当的同步对象 在C#中让线程同步的另一种编码方式就是使用线程锁.所谓线程锁,就是锁住一个资源,使得应用程序只能在此刻有一个线程访问该资源.可以用下面这句不是那么 ...
- 编写高质量代码改善C#程序的157个建议——建议77: 正确停止线程
建议77: 正确停止线程 开发者总尝试对自己的代码有更多的控制.例如,“让那个还在工作的线程马上停止下来”.然而,并非我们想怎样就可以怎样的,这至少涉及两个问题. 第一个问题 正如线程不能立即启动一样 ...
- [转]改善C#程序的建议4:C#中标准Dispose模式的实现
需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象: 非托管资源:不 ...
- 改善C#程序的建议1:非用ICloneable不可的理由
原文:改善C#程序的建议1:非用ICloneable不可的理由 好吧,我承认,这是一个反标题,实际的情况是:我找不到一个非用ICloneable不可的理由.事实上,接口ICloneable还会带来误解 ...
- 正确停止线程的方式三 使用Thread类中的内置的中断标记位-----------不熟悉
package charpter10; public class Processor implements Runnable { @Override public void run() { for ( ...
随机推荐
- Atitit phpstorm配置attilax总结
Atitit phpstorm配置attilax总结 1. 前期准备 1 1.1. 配置interpreter 1 1.2. debug需要xdebug的支持,不管是script模式还是web模式 3 ...
- 【Spark 深入学习 04】再说Spark底层运行机制
本节内容 · spark底层执行机制 · 细说RDD构建过程 · Job Stage的划分算法 · Task最佳计算位置算法 一.spark底层执行机制 对于Spark底层的运行原理,找到了一副很好的 ...
- ORGANISING THE TEST CASES
ORGANISING THE TEST CASES -Test note of “Essential Software Test Design” 2015-09-24 目录 22.1 Test Cas ...
- 小patch(psu)的打法 -- 实例
从patch中的readme来. bug:10214450 测试数据: SQL> create table t (t timestamp); Table created. SQL ...
- 【平差软件学习---科傻】四、科傻二等水准平差(参数设置和in1文件讲解)
[平差软件学习---科傻]四.科傻二等水准平差(参数设置和in1文件讲解) 这个算是最后一集了,也可能不是如果我想到不足的地方我会在补上一集视频,或者是文章页.总感觉自己操作的很熟练,到自己真正讲的时 ...
- 【30集iCore3_ADP出厂源代码(ARM部分)讲解视频】30-7底层驱动之滴嗒定时器
视频简介:该视频介绍iCore3应用开发平台中的配置方法,以及在应用开发平台中的应用. 源视频包下载地址:链接:http://pan.baidu.com/s/1o7UuUwi 密码:14cx 银杏科技 ...
- EasyUI Form提交后json数据IE上需要下载(转)
EasyUI Form提交后json数据IE上需要下载(转) 在使用EasyUI的form中的submit方法时,返回json在IE中变成提示下载的问题,代码如下: $('#fileForm'). ...
- 关于ECMP 等价路由
1.ECMP简介 Equal-CostMultipathRouting,等价多路径.即存在多条到达同一个目的地址的相同开销的路径.当设备支持等价路由时,发往该目的 IP 或者目的网段的三层转发流量就可 ...
- Java如何将每个单词的第一个字符转为大写?
在Java编程中,如何将每个单词的第一个字符转为大写? 以下示例演示如何使用toUpperCase(),appendTail()方法将字符串中每个单词的第一个字母转换为大写字母. package co ...
- PM2 指令简介
pm2 是一个带有负载均衡功能的Node应用的进程管理器.当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完美的,下面我们来看pm2常用的命令用法介绍吧 ...