Microsoft .Net Framework 提供了一个标准的取消操作的模式。这个模式是协作式的,意味着你想取消的操作必须显示地支持取消。

CLR为我们提供了两个类:

  System.Threading.CancellationTokenSource

  System.Threading.CancellationToken

CancellationToken实例是一个轻量级的值类型,因为它包含单个私有字段:CancellationTokenSource的一个引用。在一个计算限制操作的循环中,可以定时调用CancellationToken的IsCancellationRequested属性,了解循环是否应该提前终止,进而终止计算机限制的操作。

我附上我常用代码:

CancellationTokenSource cancel=new CancellationTokenSource();

    Task.Factory.StartNew(() =>
{
while (!cancel.IsCancellationRequested)
{
//do something
}
}, cancel.Token);// cancel.Token->CancellationToken //取消操作
cancel.Cancel();
cancel.Dispose();
cancel=null;

如果用到线程池,也可以使用这个类

  public void main()
{
var cancel=new CancellationTokenSource();
ThreadPool.QueueUserWorkItem(_ =>
{
while (!cancel.IsCancellationRequested)
{
//do something
}
}); Thread.Sleep( * );//为了让循环多做些时间
cancel.Cancel();
cancel.Dispose();
}

这个类还有一个很好的地方,可以在自定义回调函数,在调用Cancel方法的时候使用。这个我们需要用到CancellationToken里面的Register方法(也就是new CancellationTokenSource().Token.Register(()=>{})),并且可以给一个Token多次注册,按照倒序执行。

 var cancel = new CancellationTokenSource();
cancel.Token.Register(() =>
{
MessageBox.Show("Register3");
});
cancel.Token.Register(() =>
{
MessageBox.Show("Register");
});
cancel.Token.Register(() =>
{
MessageBox.Show("Register1");
});
cancel.Token.Register(() =>
{
MessageBox.Show("Register2");
});

弹出顺序:Register2,Register1,Register,Register3

如果想注销注册的回调函数,需要用到CancellationTokenRegistration(这个在调用Register的时候就会返回),附代码:

        CancellationTokenRegistration registration = cancel.Token.Register(() =>
{
MessageBox.Show("Register2");
});
registration.Dispose();//这里可以取消

取消以后再跑,就只会弹出另外三个,还是倒序。

最后,可通过链接另一组CancellationTokenSource来新建一个CancellationTokenSource对象,任何链接的CancellationTokenSource被取消,这个新的CancellationTokenSource对象就会自动被取消,附代码:

  public static void Go()
{
var cts1 = new CancellationTokenSource();
cts1.Token.Register(() => Console.WriteLine("cts1 canceled")); var cts2 = new CancellationTokenSource();
cts2.Token.Register(() => Console.WriteLine("cts2 canceled")); var linkedcts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
linkedcts.Token.Register(() => Console.WriteLine("linkedcts canceled")); cts2.Cancel(); Console.WriteLine("cts1:{0} cts2:{1} linkedcts:{2}",
cts1.IsCancellationRequested, cts2.IsCancellationRequested, linkedcts.IsCancellationRequested);
}

由于cts2对象被取消了,所以linkedcts自动被取消,这里CancellationTokenSource.CreateLinkedTokenSource 有一个重载是params CancellationToken[], 理论上说,无论加多少个CancellationToken对象都是可以的。

【C#】线程协作式取消的更多相关文章

  1. 协作式取消 CancellationTokenSource

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  2. C#协作试取消线程

    https://segmentfault.com/q/1010000017109927using System; using System.Collections.Generic; using Sys ...

  3. 第41天学习打卡(死锁 Lock synchronized与Lock的对比 线程协作 使用线程池)

    死锁 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形.某一个同步块同时拥有"两个以上对象的锁"时 ...

  4. 基于 Java 2 运行时安全模型的线程协作--转

    在 Java 2 之前的版本,运行时的安全模型使用非常严格受限的沙箱模型(Sandbox).读者应该熟悉,Java 不受信的 Applet 代码就是基于这个严格受限的沙箱模型来提供运行时的安全检查.沙 ...

  5. java线程系列之三(线程协作)

    本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7433673,转载请注明. 上一篇讲述了线程的互斥(同步),但是在很多情况 ...

  6. GPU编程自学5 —— 线程协作

    深度学习的兴起,使得多线程以及GPU编程逐渐成为算法工程师无法规避的问题.这里主要记录自己的GPU自学历程. 目录 <GPU编程自学1 -- 引言> <GPU编程自学2 -- CUD ...

  7. JAVA并发-线程协作

    这段时间有点忙,技术博客更新的比较少,今天更新一下相关并发的常用线程协作的类吧. ExecutorService 线程池,用于创造和复用线程,他有几种模式. 我举一个自定义线程池数量的例子如下 Exe ...

  8. CUDA线程协作之共享存储器“__shared__”&&“__syncthreads()”

    在GPU并行编程中,一般情况下,各个处理器都需要了解其他处理器的执行状态,在各个并行副本之间进行通信和协作,这涉及到不同线程间的通信机制和并行执行线程的同步机制. 共享内存"__share_ ...

  9. Java多线程之线程协作

    Java多线程之线程协作 一.前言 上一节提到,如果有一个线程正在运行synchronized 方法,那么其他线程就无法再运行这个方法了.这就是简单的互斥处理. 假如我们现在想执行更加精确的控制,而不 ...

随机推荐

  1. 不停止MySQL服务增加从库的两种方式

    不停止MySQL服务增加从库的两种方式 转载自:http://lizhenliang.blog.51cto.com/7876557/1669829 现在生产环境MySQL数据库是一主一从,由于业务量访 ...

  2. 删除数据报ORA-00600: internal error code, arguments: [ktbesc_plugged]

    Oracle在删除数据是以下错误: ORA-00600: internal error code, arguments: [ktbesc_plugged], [], [], [], [], [], [ ...

  3. Conway's Game of Life: An Exercise in WPF, MVVM and C#

    This blog post was written for the Lockheed Martin Insight blog, sharing here for the external audie ...

  4. Centos7 改名问题

    先看这篇 深入理解Linux修改hostname http://www.cnblogs.com/kerrycode/p/3595724.html  我使用如下方法 http://www.linuxid ...

  5. 文件系统管理 之 Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍

    一.df 命令:df 是来自于coreutils 软件包,系统安装时,就自带的:我们通过这个命令可以查看磁盘的使用情况以及文件系统被挂载的位置: 举例: [root@localhost beinan] ...

  6. ecshop商品详细描述调用商品相册代码

    该修改方法让用户体验更好,特别是ecshop建站的用户产品描叙文字不多的朋友,直接让相册图显示在产品描述里.免去除在后台添加了 <div style="text-align:cente ...

  7. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】【实验一】流水灯模块

    实验一:流水灯模块 对于发展商而言,动土仪式无疑是最重要的任务.为此,流水灯实验作为低级建模II的动土仪式再适合不过了.废话少说,我们还是开始实验吧. 图1.1 实验一建模图. 如图1.1 所示,实验 ...

  8. hive报lzo Premature EOF from inputStream错误

    今天dw组同事发邮件说有一个问题让帮解决一下.他们自己没能搞得定.下面问题解决过程: 1.hql insert overwrite table mds_prod_silent_atten_user p ...

  9. win7中安装redis

    1.下载redis安装版本 https://github.com/rgl/redis/downloads 2.设置环境变量 将redies的安装目录设置为环境变量 参考: http://www.cnb ...

  10. 修改windows密码后ssrs报错

    昨夜修改了windows的登录密码,第二日发现ssrs全部无法访问.显示filenotfound等错误.细想一下,应该是修改了windows的密码导致ssrs权限验证失败. 因此将ssrs的服务帐号修 ...