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. 今日 使用ajaxfileupload 异步上传 但是在IE下面 会弹出下载框

    本来以为ajaxfileupload.js的问题 后来发现 其实是 后台代码返回来的时候 修改context.Response.ContentType = "text/html"; ...

  2. VS2013 修改TFS的本地映射路径

    在源代码管理器里面 找到你的本地工作区 然后点击编辑按钮 修改本地目录

  3. window下,加载redis拓展

    下载地址: http://windows.php.net/downloads/pecl/snaps/redis/2.2.5/ 看下自己phpinfo的信息          就选择   ts-x86 ...

  4. Android 5.0 双卡信息管理分析

    首先,如前面的博文所讲的,Android5.0开始支持双卡了.另外,对于双卡的卡信息的管理,也有了实现,尽管还不是完全彻底完整,如卡的slot id, display name,iccid,color ...

  5. dapper 操作类封装

    using System; using System.Collections.Generic; using System.Data; using System.Data.SQLite; using S ...

  6. emoji和utf8mb4字符集

    mysql 的 utf8 不支持 emoji,需要修改设置为utf8mb4 <?php 'mysql' => [ 'charset' => 'utf8mb4', 'collation ...

  7. java生成解析xml的另外两种方法JAXB

     JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术.该过程中,JAXB也提供了将XML实例文档反 ...

  8. eclipse 启动后,闪退

    网上的大部分是说删除 .metadata    说会workspace里面项目会消失 下面这个可以启动,项目还在 最好解决办法: 删除文件 [workspace]/.metadata/.plugins ...

  9. iOS开发——项目实战总结&Block使用注意点浅析

    Block使用注意点浅析 1.在使用block前需要对block指针做判空处理. 不判空直接使用,一旦指针为空直接产生崩溃. if (!self.isOnlyNet) { if (succBlock ...

  10. ubuntu-15.04-server-i386.iso 安装 Oracle 11gR2 数据库

    特点: 需要重新安装老版本的 libaio1_0.3.109-2ubuntu?_i386.deb.默认的libaio库有问题,和其默认libaio的编译方式有关! 默认的gcc 4.9 需要使用 -W ...