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);
}
}
输出:
在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);
}
}
}
输出:
来源:https://www.cnblogs.com/afei-24/p/6917767.html


猜你喜欢
- 本文实例为大家分享了Java实现学生管理系统的具体代码,供大家参考,具体内容如下package BookDemo_1; import jav
- AndroidStduio3.0使用gradle将module打包jar文件,首先需要安装gradle。打开控制台输入  
- 在本篇博文中,我们主要讲解一下 IntelliJ IDEA 安装目录中的一些核心文件的功能及用法:如上图所示,我们定位到了 IntelliJ
- 一、创建支付宝沙箱跳转 : 支付宝沙箱平台1、进入控制台2、创建小程序,编写名称和绑定商家即可3、返回第一个页面,往下滑进入沙箱4、进行相关
- springboot与spring区别一、spring 可以做什么之前已经学习了 spring 的 IOC容器、AOP、springMVC
- 使用环境项目环境:Idea 2020.2.3、 Maven 3.6.3 、springboot 2.1.4本人在创建springboot项目
- 日常的开发中经常会需要用到自定义View,这次刚好有个需求,需要用到带有节点的进度条。东西很简单直接继承View就行了。首先定义一些需要的属
- 这篇文章主要介绍了新手学习微服务SpringCloud项目架构搭建方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "hello";,另一种就是使用new
- 在本篇中我要介绍两个概念,我觉得这两个东西必须一起来介绍,这样才能连贯。C# 2.0里我们已经匿名方法了,现在类型也玩起匿名来了,怪不得大家
- Jakarta commons fileupload组件可以处理HTTP请求及响应,很多时候被用来处理文件上传,但是近期发现,当我们自定义文
- 前言本篇开始讲解音频编辑的具体操作,从相对简单的音频裁剪开始。要进行音频裁剪,我的方案是开启一个Service服务用于音频裁剪的耗时操作,主
- 目录存储权限内部存储 外部存储适配存储权限Android Q 仍然使用 READ_EXTRNAL_STORAGE 和 WRITE_EXTRN
- JetBrains JVM Debugger Memory View plugin在我最近的研发活动期间寻找新的工具,以提高我的开发经验,使
- 本文实例讲述了C#中使用ADOMD.NET查询多维数据集的实现方法,分享给大家供大家参考。具体实现方法分析如下:ADOMD.NET 是用于与
- 资源下载:点此下载一、语言和环境1.实现语言: JAVA语言。2.环境要求: MyEclipse/Eclipse + Tomcat + My
- using System;using System.Collections.Generic;using System.Linq;using
- 本文实例讲述了C#中的事务用法。分享给大家供大家参考。具体如下:直接用SQL语句创建事务, 当然不是什么稀奇事了, 好是好, 只是麻烦.看看
- 还原背景大家都做过b-s架构的应用,也就是基于浏览器的软件应用。现在呢有个场景就是FE端也就是前端工程是前后端分离的,采用主流的前端框架VU
- 目录多开理论基础多开实现原理解析代码实现:多开包名代码实现:多用户总结多开理论基础app多开常用于做一些不合法的事情,如高羊毛,黑灰产,甚至