在.net 4.0中,引入了一个新的类CancellationToken,这个类基本上集成了我们各种常用的取消方式,在并发任务中非常有用。

同步模式下的取消:

一种比较常见的需要支持取消功能的的是一些比较耗时的分段操作:如视频转换,网络下载等,这种方式下的取消机制如下:

  1. 建立一个标记位,表示该操作是否已经取消
  2. UI线程在获取到取消事件后,置标记位为true
  3. 耗时的操作线程里,没进行一小段操作之后查询该标记位,如果为true则主动退出。

使用方式如下:

EventHandler externalEvent;     void Example1()     {         CancellationTokenSource cts = new CancellationTokenSource();         externalEvent +=            (sender, obj) => { cts.Cancel(); }; //wire up an external requester         try         {             int val = LongRunningFunc(cts.Token);         }         catch (OperationCanceledException)         {             //cleanup after cancellation if required...         }     }
    private static int LongRunningFunc(CancellationToken token)     {         int total = 0;         for (int i = 0; i < 1000; i++)         {             for (int j = 0; j < 1000; j++)             {                 total++;             }             if (token.IsCancellationRequested)             { // observe cancellation                 throw new OperationCanceledException(token); // acknowledge cancellation             }         }         return total;     }

异步模式下的取消

另外一种常见的方式是在一些异步操作中,往往不能主动释放,只能等待异步操作回调的时候才能操作结果。此时一般取消方法如下:

  1. 任务线程注册异步操作完成的回调函数,开始异步操作。
  2. UI线程接受取消指令,置取消标记位,并主动执行回调函数
  3. 回调函数中通过取消标记位判断该任务是已经完成还是被取消的,并执行相关析构操作。

使用方式如下:

void BlockingOperation(CancellationToken token)     {         ManualResetEvent mre = new ManualResetEvent(false);         //register a callback that will set the MRE         CancellationTokenRegistration registration =            token.Register(() => mre.Set());         using (registration)         {             mre.WaitOne();             if (token.IsCancellationRequested) //did cancellation wake us?                 throw new OperationCanceledException(token);         } //dispose the registration, which performs the deregisteration.     }

这里我们通过CancellationToken注册了一个回调方法以通知任务等待线程,也可以以我们经常使用的WaitHandle的那样的方式使用。

void Wait(WaitHandle wh, CancellationToken token)     {         WaitHandle.WaitAny(new[] { wh, token.WaitHandle });         if (token.IsCancellationRequested) //did cancellation wake us?             throw new OperationCanceledException(token);     }

高级应用

由于例子比较简单,这里就只列举一下代码,不多介绍了。

一个CancellationToken对应多个任务

void Example4()     {         CancellationTokenSource cts = new CancellationTokenSource();         Func1(cts.Token);         Func2(cts.Token);         Func3(cts.Token);         //...         cts.Cancel(); // all listeners see the same cancellation request.     }

一个任务对应多个CancellationToken

void LinkingExample(CancellationToken ct1, CancellationToken ct2)     {         CancellationTokenSource linkedCTS =         CancellationTokenSource.CreateLinkedTokenSource(ct1, ct2);         try         {             SlowFunc(linkedCTS.Token);         }         catch (OperationCanceledException oce)         {             if (ct1.IsCancellationRequested)             {                 // ...             }             else if (ct2.IsCancellationRequested)             {                 // ...             }         }         linkedCTS.Dispose(); // clean up the linking. required.     }

最后我们再来一个并发查询时取消的例子:

private void RunQuery()     {         int[] data = { 1, 2, 3 };         CancellationTokenSource cts = new CancellationTokenSource();         var query = data.AsParallel()                      .WithCancellation(cts.Token) // token given to library code                      .Select((x) => SlowFunc(x, cts.Token)); // token passed to user code     }
    private int SlowFunc(int x, CancellationToken token)     {        int result        while(...)        {           if (token.IsCancellationRequested)              throw new OperationCanceledException(token);           ...        }        return result;     }

小结

.net 4.0中的Cancellation Framework还是非常实用的,通过它可以更有效的简化及规范的使用各种取消的操作方式,由于我也只会皮毛,在这里也只是介绍了它的基本用法,在后续的学习和应用中将继续进一步介绍。

转载于:https://www.cnblogs.com/zjoch/p/3508301.html

.Net4.0并行库介绍——Cancellation Framework相关推荐

  1. .NET4.0并行计算技术基础(8)

    说明: 要想看懂本系列文章,需要您对.NET多线程开发有基本的了解.我在新书<面向对象的艺术 --.NET Framework 4.0技术剖析与应用>(暂名)中花了近200页的篇幅来介绍. ...

  2. .Net 4.0并行库实用性演练[1]

    自VS2010发布近半年了,虽然整天想学习新东西,要更新到自己时,发现原来自己基本也很懒,2008还没用上多久呢,无奈被2010了.用了几天,IDE模样还是和05.08差不多,加了些小特性,以后慢慢体 ...

  3. Net 4.0并行库实用性演练

    引言 随着CPU多核的普及,编程时充分利用这个特性越显重要.上篇首先用传统的嵌套循环进行数组填充,然后用.NET 4.0中的System.Threading.Tasks提供的Parallel Clas ...

  4. .Net并行库介绍——Task(1)

    Task和ThreadPool的功能类似,可以用来创建一些轻量级的并行任务.对于将一个任务放进线程池     ThreadPool.QueueUserWorkItem(A); 这段代码用Task来实现 ...

  5. .Net 4.0并行库实用性演练

    前面说在练习Parallel时,发现另有乾坤,是这样的代码: 代码 static IEnumerable<Person> testFill() { var list =new List&l ...

  6. 详细介绍百度ERNIE 2.0:A Continual Pre-Training Framework for Language Understanding

    系列阅读: 详细介绍百度ERNIE1.0:Enhanced Representation through Knowledge Integration 详细介绍百度ERNIE 2.0:A Continu ...

  7. Windows7安装Framework .NET4.0失败

    安装CAD2007 CAD2014等需要Framework .NET4.0始终无法安装成功,总是提示 "安装时发生严重错误",看log发现返回"Installation ...

  8. iOS架构-静态库.a 和.framework的区别(0)

    原文网址:https://my.oschina.net/kaqijiang/blog/649632 一.什么是库? 库是共享程序代码的方式. 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存 ...

  9. C#多线程开发-任务并行库

    你好,我是阿辉. 正文共2090字,预计阅读时间:6min. 之前学习了线程池,知道了它有很多好处. 使用线程池可以使我们在减少并行度花销时节省操作系统资源.可认为线程池是一个抽象层,其向程序员隐藏了 ...

最新文章

  1. Android Studio 的安装笔记
  2. mvc ajax教程,MVC3----AJAX辅助方法
  3. SpringMVC接收checkbox传值
  4. C语言 满分代码:L1-043 阅览室 (20分)(解题报告)
  5. google天气预报接口_将天气预报添加到谷歌浏览器
  6. python调用带参函数_Python | 带有示例的函数调用类型
  7. 建立丰富多彩的toast的简单实例
  8. 线程销毁_多线程(2)-Java高级知识(9)
  9. eclipse一些实用小技巧
  10. 【学习笔记】尚硅谷大数据项目之Flink实时数仓---DWD和DIM
  11. wgs84坐标系拾取工具_Wgs84坐标系转换为gcj02坐标系及bd09坐标系的验证
  12. 细粒度分类:Hierarchical Bilinear Pooling(HBP),分级双线性池化(一)
  13. SpringBoot+zxing批量生成二维码_南国
  14. 基于安卓的共享自习室的设计与实现
  15. 卸载重装Ubuntu22.04双系统
  16. 最短Hamilton路径(哈密顿图,状压dp)
  17. BOM中的location对象
  18. 【菜菜的sklearn课堂笔记】决策树-分类树
  19. 安卓使用connectbot连接centos云服务器
  20. Ecshop 表结构 字段说明

热门文章

  1. python装饰器深度讲解_python核心知识讲解,干货!!!
  2. matlab循环标注,for循环
  3. Linux 内核网络协议栈运行原理
  4. 【必看】运维是“越老越吃香“的职业?
  5. 如何发现 Kubernetes 中服务和工作负载的异常
  6. java hook 框架_hook框架-frida简单使用模板以及frida相关接口
  7. linux系统编译安装mysql_Linux下编译安装MySQL
  8. git reset 怎么还原_git reset –hard后的恢复操作
  9. sql截去最后一位_sql 取最后一条记录
  10. chart控件做实时曲线显示_用PyQt5.QtChart实现动态曲线图