C# 取消一个不带CancellationToken的任务?

        在异步函数中,一般使用CancellationToken来控制函数的执行。这个Token需要作为参数传递到异步函数中:

public staic Task<T> DoAsync(CancellationToken token)
{...
}

        那么如果一个异步函数没有这个Token参数,如何取消呢?

        之前看到一个博客:How to Cancel a Non-Cancellable Task in C#


1.构建取消异步函数的扩展方法

        先上代码:

    public static class TaskExtensions{public static async Task<T> WithCancellation<T> (this Task<T> task,CancellationToken cancellationToken){var tcs=new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);using (cancellationToken.Register(state =>{((TaskCompletionSource<object>)state!).TrySetResult(null!);}, tcs)){var resultTask = await Task.WhenAny(task, tcs.Task);if(resultTask==tcs.Task){throw new OperationCanceledException(cancellationToken);}return await task;}}}

        显然这是一个扩展方法,旨在为Task<T>类型扩展一个名叫WithCancellation函数。这个函数会有一个CancellationToken,但这个Token不是传递给任务参数task(也就是我们要取消的函数)的,而是用于外部控制。

        代码中首先构建了一个异步任务,利用TaskCompletionSource<T>,可以构建一个用于控制原任务的异步任务,这里的TaskCompletionSource不多解释了,可以参考博客:here。然后通过传入的Token注册一个回调函数,回调函数传入的参数就是刚刚创立的TaskCompletionSource<T>对象,回调函数会调用成员函数TrySetResult()给任务赋值。而回调函数的执行则是在Token被取消时触发。

2. 测试

        然后我们使用这个扩展方法构建实例:

 internal class CancelTaskWithoutCancellationToken{private static readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();public static async Task Test(){try{var result = await Task.Run(async () =>{await Task.Delay(TimeSpan.FromSeconds(5));Console.WriteLine("操作完成");await Task.Delay(300);Console.WriteLine("还继续吗?");return 7;}).WithCancellation(cancellationTokenSource.Token);Console.WriteLine(result.ToString());}catch (Exception ex){Console.WriteLine(ex.Message);Console.WriteLine("任务取消了");}finally{cancellationTokenSource.Dispose();}}public static void Cancel(){cancellationTokenSource?.Cancel();}}

测试代码:

var t1=CancelTaskWithoutCancellationToken.Test();
var t2 = Task.Run(() =>
{Thread.Sleep(1000);CancelTaskWithoutCancellationToken.Cancel();
});
await Task.WhenAll(t1, t2);

运行结果如下:

好像结果很符合预期。

假设测试代码后面还有一些任务要运行,也就是主线程没那么快结束呢?让我们在测试代码后面加一行:

var t1=CancelTaskWithoutCancellationToken.Test();
var t2 = Task.Run(() =>
{Thread.Sleep(1000);CancelTaskWithoutCancellationToken.Cancel();
});
await Task.WhenAll(t1, t2);
Console.WriteLine("----------------------");
Console.ReadLine();

运行结果:

        Oh No,原来的任务还是执行了,说明没能阻止那个任务继续运行,所以原博客说取消一个不能被取消的任务(non-cancelable)是错的,开工没有回头箭。但是从前面的例子,我们可以取消等待那个任务。

        实际上博主在另外一篇博客找到了关于这个问题的说明:

 How do I cancel non-cancelable async operations?

        博主在最后总结:

So, can you cancel non-cancelable operations? No.  Can you cancel waits on non-cancelable operations?  Sure… just be very careful when you do.

        所以,如果想能随时取消一个Task,最稳妥的办法还是将Token作为参数传递进去

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/109615.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TODO Vue typescript forEach的bug,需要再核實

forEach 一個string[]&#xff0c;只有最後一個匹配條件有效&#xff0c;其它條件無效。 所以&#xff0c;只能替換成普通的for循環。 console.log(taskList)// for (const _task of taskList.value) {// if (_task invoiceSendEmail) {// form.value.invoiceSendEmail…

Hadoop3教程(十五):MapReduce中的Combiner

文章目录 &#xff08;103&#xff09;Combiner概述什么是CombinerCombiner有什么用处Combiner有什么特点如何自定义Combiner &#xff08;104&#xff09;Combiner合并案例实操如何从日志里查看Combiner如果不存在Reduce阶段&#xff0c;会发生什么自定义Combiner的两种方式 参…

【非root用户、CentOS系统】中使用源码安装gcc/g++的教程

1.引言 系统&#xff1a;CentOS-7.9 显卡驱动版本&#xff1a;460 CUDA Version: 11.2 &#x1f33c;基于本地环境选择安装gcc-10.1.0 &#x1f449; gcc下载网址 2.安装说明 下载好对应的gcc的安装包并解压&#xff1a; 打开gcc-10.1.0/contrib/download_prerequisites&#…

关于gt_sampling的理解

pcdet/datasets/augmentor/data_augmentor.py def gt_sampling(self, configNone):db_sampler database_sampler.DataBaseSampler(root_pathself.root_path,sampler_cfgconfig,class_namesself.class_names,loggerself.logger)return db_sampler此函数指向DataBaseSampler类&a…

0基础学习VR全景平台篇第109篇:认识拼接软件PTGui Pro

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01;今天给大家讲解我们全景后期拼接软件PTgui pro&#xff0c;下面我们开始吧&#xff01; &#xff08;PTgui pro软件课程大纲&#xff09; 1.PTGui这个软件是什么 发明人 &#xf…

【网络编程】从网络编程、TCP/IP开始到BIO、NIO入门知识(未完待续...)

目录 前言前置知识一、计算机网络体系结构二、TCP/IP协议族2.1 简介*2.2 TCP/IP网络传输中的数据2.3 地址和端口号2.4 小总结 三、TCP/UDP特性3.1 TCP特性TCP 3次握手TCP 4次挥手TCP头部结构体 3.2 UDP特性 四、总结 课程内容一、网络通信编程基础知识1.1 什么是Socket1.2 长连…

Python之旅----判断语句

布尔类型和比较运算符 布尔类型 布尔类型的定义 布尔类型的字面量&#xff1a; True 表示真&#xff08;是、肯定&#xff09; False 表示假 &#xff08;否、否定&#xff09; 也就是布尔类型进行判断&#xff0c;只会有2个结果&#xff1a;是或否 定义变量存储布尔类型…

天猫店铺商品评论数据采集,天猫商品评论数据接口,天猫API接口

天猫店铺商品评论数据接口可以获取到商品ID&#xff0c;商品标题&#xff0c;商品优惠券&#xff0c;商品到手价&#xff0c;商品价格&#xff0c;商品优惠价&#xff0c;商品sku属性&#xff0c;商品图片&#xff0c;商品视频&#xff0c;商品sku属性图片&#xff0c;商品属性…

ant中的environment属性

在ant的配置文件中&#xff0c;可以设置属性environment的值&#xff0c;设置的这个值就作为访问环境变量的前缀。例如声明了environment“env”&#xff0c;那么就可以通过env.<环境变量名称>来访问环境变量。 例如创建了一个Java工程&#xff0c;在工程目录下有一个bu…

HCIA --- VLAN实验配置

一、各交换机上配置&#xff1a; 1、各交换机上创建VLAN 2、交换机上的各个接口划分到对应的VLAN中 3、将与交换机、路由器相连的接口创建trunk干道 SW1&#xff1a; [sw1]vlan batch 2 to 3 批量创建VLAN2-3 [sw1]interface Ethernet0/0/1 单独将某个接口划分到对应…

信息保卫战:揭秘迅软DSE护航企业免受泄密之害

随着网络技术的发展&#xff0c;通过网络应用如网盘、网页、邮件、即时通讯工具传输分享文件变得越来越多&#xff0c;这些工具传输速度快&#xff0c;能够将大容量的文档快速传送给他人&#xff0c;在工作中受到许多人的青睐。 然而由这些传输工具引发的泄密事件也不断增多&am…

视频怎么压缩?视频太大这样处理变小

在当今时代&#xff0c;视频已经成为了我们日常生活中不可或缺的一部分&#xff0c;然而&#xff0c;视频文件往往非常大&#xff0c;给我们的存储和传输带来了很大的不便&#xff0c;那么&#xff0c;如何有效地压缩视频呢&#xff1f; 一、使用压缩软件 首先我们给大家分享一…

供应商工厂突发爆炸,日本丰田7座工厂停工 | 百能云芯

根据日本共同社的最新报导&#xff0c;日本著名汽车制造商丰田汽车近期遭遇了一系列生产中断问题。这次生产中断的根本原因在于供应商公司发生了一起爆炸事件&#xff0c;导致零部件供应链受到了严重干扰&#xff0c;迫使丰田暂时停工。截至目前&#xff0c;这一事件已经影响了…

【触想智能】工业级触摸显示器的分类与应用分享

工业级触摸显示器是具有触摸功能的工业显示器&#xff0c;常见的触摸方式有电容触摸和电阻触摸。它是应用在工业上的设备&#xff0c;和普通的显示器有着很大的区别。 工业级触摸显示器由液晶触摸屏、功能主板、外壳三部分组成&#xff0c;结构用料一般都采用铝合金材质&#x…

配电房无人值守方案

随着科技的不断进步&#xff0c;许多传统需要人工操作和维护的领域逐渐被自动化和智能化方案所替代。配电房作为电力供应的核心部分&#xff0c;也面临着同样的变革。 力安科技电易云配电室无人值守监控系统以智能物联数据采集和智能物联管控"为关键&#xff0c;通过加…

自动化测试必会之数据驱动测试

数据驱动测试 在实际的测试过程中&#xff0c;我们会发现好几组用例都是相同的操作步骤&#xff0c;只是测试数据的不同&#xff0c;而我们往往需要编写多次用例来进行测试&#xff0c;此时我们可以利用数据驱动测试来简化该种操作。 参数化&#xff1a; 输入数据的不同从而产…

Linux性能优化--性能工具:特定进程内存

5.0 概述 本章介绍的工具使你能诊断应用程序与内存子系统之间的交互&#xff0c;该子系统由Linux内核和CPU管理。由于内存子系统的不同层次在性能上有数量级的差异&#xff0c;因此&#xff0c;修复应用程序使其有效地使用内存子系统会对程序性能产生巨大的影响。 阅读本章后&…

反转链表(java)

大家好我是苏麟今天说一说链表常见的简单题目 . BM1 反转链表 牛客BM1 反转链表 : 描述 : 给定一个单链表的头结点(该头节点是有值的&#xff0c;比如在下图&#xff0c;它的val是1)&#xff0c;长度为n&#xff0c;反转该链表后&#xff0c;返回新链表的表头。 分析 : …

安装thinkphp6并使用多应用模式,解决提示路由不存在解决办法

1. 安装稳定版tp框架 composer create-project topthink/think tptp是安装完成的目录名称 &#xff0c;可以根据自己需要修改。 如果你之前已经安装过&#xff0c;那么切换到你的应用根目录下面&#xff0c;然后执行下面的命令进行更新&#xff1a; composer update topthin…

一百九十、Hive——Hive刷新分区MSCK REPAIR TABLE

一、目的 在用Flume采集Kafka中的数据直接写入Hive的ODS层静态分区表后&#xff0c;需要刷新表&#xff0c;才能导入分区和数据。原因很简单&#xff0c;就是Hive表缺乏分区的元数据 二、实施步骤 &#xff08;一&#xff09;问题——在Flume采集Kafka中的数据写入HDFS后&am…