C# Task 取消执行的简单封装
我让DeepSeek帮我写了一段使用 CancellationTokenSource 取消任务的简单示例如下:
取消任务的简单示例
using System.Threading.Tasks;
using System.Threading;
public async Task Test()
{
var cts = new CancellationTokenSource();
var task = Task.Run(() =>
{
while (true)
{
cts.Token.ThrowIfCancellationRequested();
Thread.Sleep(200);
}
});
await Task.Delay(1000);
cts.Cancel();
try
{
await task;
}
catch (OperationCanceledException)
{
// task is cancelled
}
finally
{
cts.Dispose();
}
}
相对于不可取消的普通任务多了很多代码,并且终止任务的方式 ThrowIfCancellationRequested 内部是通过抛出异常实现的
ThrowIfCancellationRequested 内部代码
public void ThrowIfCancellationRequested()
{
if (IsCancellationRequested)
{
throw new OperationCanceledExceptionEx(this);
}
}
于是我就想自己封装一个简单的包装类,代码如下:
CancelableTask
namespace System.Threading.Tasks
{
public sealed class CancelableTask : Task
{
readonly object cancelLock = new object();
CancellationTokenSource cts;
public bool IsCancellationRequested => cts != null && cts.IsCancellationRequested;
private CancelableTask(Action action, CancellationToken token) : base(action, token) { }
protected override void Dispose(bool disposing)
{
if (disposing)
{
cts?.Dispose();
}
base.Dispose(disposing);
}
public void Cancel()
{
lock (cancelLock)
{
if (!IsCompleted && !IsCancellationRequested)
{
cts.Cancel();
}
}
}
public static CancelableTask StartNew(Action action)
{
var cts = new CancellationTokenSource();
var task = new CancelableTask(action, cts.Token);
task.cts = cts;
task.Start();
return task;
}
public static void Restart(ref CancelableTask task, Action action)
{
var oldTask = Interlocked.Exchange(ref task, null);
oldTask?.Cancel();
var newTask = StartNew(action);
Interlocked.Exchange(ref task, newTask);
}
}
}
此类公开了 Cancel 用来取消任务,静态的 StartNew 用来创建新实例,以及静态的 Restart 用来取消上个任务并重启任务,
还公开了一个 IsCancellationRequested 属性用来获取是否请求过取消任务,相对于调用 ThrowIfCancellationRequested 抛出异常来终止任务的方式性能更好也更加友好
使用此类重新编写上面的示例就简单很多了
CancelableTask 使用示例
using System.Threading.Tasks;
CancelableTask task;
public async Task Test()
{
task = CancelableTask.StartNew(() =>
{
while (!task.IsCancellationRequested)
{
Thread.Sleep(200);
}
});
await Task.Delay(1000);
task.Cancel();
await task;
}
C# Task 取消执行的简单封装的更多相关文章
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
- axios简单封装
写在最前面 新手前端刚刚接触vue,感觉真的好用.项目中需要使用axios,然后学习了一下.借鉴网上一些大佬的经验,现在分享一下axios的简单封装,如果有什么错误的地方,请大家指出. axios安装 ...
- FMDB简单封装和使用
工具:火狐浏览器+SQLite Manager插件 ; Xcode; FMDB库; 效果: 项目地址: https://github.com/sven713/PackFMDB 主要参考这两篇博客: 1 ...
- Android--Retrofit+RxJava的简单封装(三)
1,继续接着上一篇的讲讲,话说如果像上一篇这样的话,那么我们每一次请求一个结构都要创建一堆的Retrofit对象,而且代码都是相同的,我们可以试试封装一下 先创建一个HttpMethods类,将Ret ...
- okhttp3 get post 简单封装
最近打算在新项目中使用 okhttp3, 简单封装了一下异步 get post 因为 CallBack 也是在子线程中执行,所以用到了 Handler public class MyOkHttpCli ...
- 对pymysql的简单封装
#coding=utf-8 #!/usr/bin/python import pymysql class MYSQL: """ 对pymysql的简单封装 "& ...
- MySQL的C++简单封装
/* *介绍:MySQL的简单封装,支持流操作输入输出MySQL语句,然而并没有什么软用,大二学生自娱自乐,有不足求指点 *作者:MrEO *日期:2016.3.26 */ 头文件 my_sql.h ...
- redis数据库操作的C++简单封装
用c++简单封装了redis的基本操作(hiredis) 接口包括:①链接和断开连接.②设置键值对(set).③查询键值对(get).④删除键值对(del).⑤将所有键显示出来 若任何一处发生错误,返 ...
- DBUtils-对JDBC简单封装的开源工具类库
DBUtils 是对JDBC简单封装的开源工具类 详细介绍地址: https://baike.baidu.com/item/Dbutils/10655914?fr=aladdin 在使用DBUtil ...
- Google图片加载库Glide的简单封装GlideUtils
Google图片加载库Glide的简单封装GlideUtils 因为项目里用的Glide的地方比较多,所有简单的封装了以下,其实也没什么,就是写了个工具类,但是还是要把基础说下 Glide的Githu ...
随机推荐
- qa 工作
1.定流程--监控参照规范(cmmi,公司自己的,scrum[例会.启动会])--产出物报告 (项目维度)-配置--经盈.财务 2.培训组织-组织讲师(知识库).外部拓展
- Laravel11 从0开发 Swoole-Reverb 扩展包(四) - 触发一个广播事件到reverb服务之后是如何转发给前端订阅的呢(下)?
前情提要 上一篇我们讲到了reverb服务的通信上下文和路由处理,路由实现了pusher关联的几种请求.那么这一篇我们主要来讲混响服务Server 混响 Server 负责基于 ReactPHP 的 ...
- jquery的radio的change事件
一.用的jquery的radio的change事件:当元素的值发生改变时,会发生 change 事件,radio选择不同name值选项的时候恰巧是值发生改变 表单单选框 <input type= ...
- rsarsa-给定pqe求私钥对密文解密
题目: Math is cool! Use the RSA algorithm to decode the secret message, c, p, q, and e are parameters ...
- [WPF]XAML中使用IMultiValueConverter实现Command的多参数传参
问题 如何对ICommand传入多个参数? 背景 最近在做一个WPF的开发,有多个相近的功能写了不同的Command,因为要对应不同的对象.因为是CtrlCV,显得代码有点冗赘不够优雅,但是IComm ...
- 【VMware VCF】启动和关闭 VMware Cloud Foundation 环境的正确顺序。
为了避免出现数据丢失以及保证 SDDC 组件的正常运行,启动和关闭 VMware Cloud Foundation 环境中的组件应该遵循特定的顺序.比如,在关闭管理工作负载域之前,应该先关闭 VI 工 ...
- Sa-Token v1.42.0 发布 🚀,新增 API Key、TOTP 验证码、RefreshToken 反查等能力
Sa-Token 是一款 免费.开源 的轻量级 Java 权限认证框架,主要解决:登录认证.权限认证.单点登录.OAuth2.0.微服务网关鉴权 等一系列权限相关问题. 目前最新版本 v1.42.0 ...
- idea git建立分支、切换分支、合并分支
为什么要建立分支 git默认的主分支名字为master,一般团队开发时,都不会在master主分支上修改代码,而是建立新分支,测试完毕后,在将分支的代码合并到master主分支上 2.操作如下: 2. ...
- 科研新体验:刘同学深度试用ADTF软件反馈揭晓!
一.前言 作为一名高校的科研工作者,在高校的科研工作中,经常需要处理各种复杂的数据流,尤其是视频采集和处理的工作,对数据的实时性和精度要求非常高,我首次试用ADTF时,主要负责开发一个集成FFmpeg ...
- [开源] Layouter(桌面助手)开源发布
Layouter(桌面助手)是一款简洁.易用.美观的桌面整理软件,基于.net 6开发,支持Windows 7及以上操作系统.以 Apache-2.0 license 进行开源. 开源地址 https ...