C#多线程之取消架构介绍

作者:Ruby_Lu 时间:2022-03-06 22:14:42 

.NET 4.5 中包含取消架构,允许以标准方式取消长时间运行的任务。每个阻塞调用都应支持这种机制。但目前,并不是所有阻塞调用都实现了这个新技术。已经实现了这种机制的技术有任务(https://www.jb51.net/article/244285.htm),并发集合类(https://www.jb51.net/article/244141.htm),并行LINQ(https://www.jb51.net/article/244216.htm)和几种同步机制。
取消架构基于协作行为,它不是强制的。长时间运行的任务会检查它是否被取消,并返回控制权。
支持取消的方法接受一个CancellationToken参数。这个类定义了IsCancellationRequested属性,其中长时间运行的操作可以检查它是否应终止。使用Register()方法注册一个将在取消此 System.Threading.CancellationToken 时调用的委托。它在调用Cancel()方法取消操作时调用。

1.Parallel.For()方法的取消

Parallel类提供了For()方法的重载版本,在重载版本中,可以传递ParallelOptions类型的参数。使用ParallelOptions类型,可以传递一个CancellationToken参数。CancellationToken参数通过创建CancellationTokenSource来生成。由于CancellationTokenSource实现了ICancelableOperation接口,因此可以用CancellationToken注册,并允许使用Cancle(),CancleAfter()等方法取消操作。
示例:

static void CancelParallelFor()
       {
           var cts = new CancellationTokenSource();
           cts.Token.Register( ()=> Console.WriteLine("token canceled!"));

cts.CancelAfter(1000);

try
           {
               ParallelLoopResult plr =
                   Parallel.For(0, 100, new ParallelOptions { CancellationToken = cts.Token },
                   x => {
                       Console.WriteLine("loop {0} started", x);
                       Thread.Sleep(1000);
                       Console.WriteLine("loop {0} fininshed!", x);
                   });
           }
           catch (OperationCanceledException ex)
           {
               Console.WriteLine(ex.Message);

}
       }

输出:

C#多线程之取消架构介绍

在For循环的实现代码中,Parallel类验证CancellationToken的结果,并取消操作。一旦取消操作,For()方法就抛出一个OperationCanceledException类型的异常。
由输出可看出,当取消操作时,已启动的操作允许完成,因为取消操作总是以协作方式进行,以避免在取消迭代操作的中间泄露资源。

2.任务的取消

任务的取消类似Parallel.For()方法的取消。首先,创建一个CancellationTokenSource。如果只需要一个取消标记,可以访问Task.Factory.CancellationToken,以使用默认的取消标记。任务通过TaskFactory对象接受取消标记。在构造函数中,把取消标记赋予TaskFactory。这个取消标记又任务用于检查CancellationToken的IsCancellationRequested属性,以确定是否请求了取消。
示例:

static void CancelTask()
       {
           var cts = new CancellationTokenSource();

cts.Token.Register(() => Console.WriteLine("task cancelled!"));

cts.CancelAfter(2000);

try
           {
               Task t = Task.Run(() =>
               {
                   CancellationToken token = cts.Token;
                   Console.WriteLine("task stared!");
                   for (int i = 0; i < 20; i++)
                   {
                       Thread.Sleep(500);
                       if (cts.IsCancellationRequested)
                       {
                           Console.WriteLine("cancelled!");
                           token.ThrowIfCancellationRequested();//抛出异常
                           break;
                       }
                       Console.WriteLine("in loop!");
                   }
               }, cts.Token);
               t.Wait();
           }
           catch (AggregateException ex)
           {
               Console.WriteLine("exception:{0},{1}",ex.GetType().Name,ex.Message);
               foreach (var innerEx in ex.InnerExceptions)
               {
                   Console.WriteLine("exception:{0},{1}", ex.InnerException.GetType().Name, ex.InnerException.Message);
               }
           }
       }

输出:

C#多线程之取消架构介绍

来源:https://www.cnblogs.com/afei-24/p/6917767.html

标签:C#,多线程,取消,架构
0
投稿

猜你喜欢

  • springboot2.0如何通过fastdfs实现文件分布式上传

    2022-03-20 16:49:24
  • Android WindowManger实现桌面悬浮窗功能

    2023-08-01 02:16:10
  • c#开发cad预览图块步骤详解

    2022-12-30 10:49:07
  • Java线程同步Lock同步锁代码示例

    2023-11-17 13:23:54
  • Windows10 Java环境变量配置过程图解

    2022-12-16 15:08:38
  • C# WinForm创建Excel文件的实例

    2023-08-06 19:47:06
  • java 保留两位小数的几种方法

    2022-05-11 16:38:27
  • Java多态中动态绑定原理解析

    2021-08-01 06:39:23
  • Java动态数组Arraylist存放自定义数据类型方式

    2023-07-25 10:41:30
  • Java字符串split使用方法代码实例

    2023-02-06 18:55:31
  • C#操作INI配置文件示例详解

    2021-11-06 11:03:01
  • Netty分布式源码分析监听读事件

    2022-10-23 20:59:43
  • C#实现动态执行字符串脚本(优化版)的示例代码

    2022-06-10 19:13:54
  • Springboot通过lucene实现全文检索详解流程

    2021-12-10 22:59:45
  • Spring Boot 与DBunit 配合使用方法

    2022-07-29 13:29:28
  • Java编程实现对象克隆(复制)代码详解

    2023-02-13 10:12:31
  • 一篇文章彻底弄懂Java中二叉树

    2023-04-08 12:47:30
  • 基于springboot 配置文件context-path的坑

    2021-07-04 17:37:27
  • Java中匿名类的两种实现方式

    2022-06-17 23:57:05
  • 设置JavaScript自动提示-Eclipse/MyEclipse

    2022-06-15 12:41:05
  • asp之家 软件编程 m.aspxhome.com