在c#中使用CancellationToken取消任务

news/2024/5/19 22:25:47 标签: c#, .netcore

目录

🚀介绍:

🐤简单举例

🚀IsCancellationRequested

🚀ThrowIfCancellationRequested

🐤在控制器中使用

 🚀通过异步方法的参数使用cancellationToken

🚀api结合ThrowIfCancellationRequested()


🚀介绍:

CancellationToken是.NET中用于协调取消操作的结构。它通常用于多线程操作,例如任务和线程等。当你启动一个新的任务或线程时,你可以传递一个CancellationToken给它,然后在其他线程中,你可以使用这个token来请求取消操作。

  • 属性:IsCancellationRequested,它的返回值是bool类型,即表示当前任务是否被取消,当调用CancellationTokenSource的Cancel方法时,与之关联的所有CancellationToken的IsCancellationRequested属性将返回true。
  • 方法:ThrowIfCancellationRequested,如果IsCancellationRequested为true,那么它将抛出一个OperationCanceledException异常。这是一种在任务中响应取消请求的常见方式。

🐳例如,你可能有一个长时间运行的任务,你希望用户能够取消。你可以传递一个CancellationToken给这个任务,然后在任务的代码中定期检查IsCancellationRequested属性,或者调用ThrowIfCancellationRequested方法。如果用户请求取消操作,那么你的任务代码将能够响应这个请求。

🐤简单举例

下面用几个简单的例子来使用IsCancellationRequested属性与ThrowIfCancellationRequested方法,更直观的展示他们的用法,在CancellationToken中我们可以直接使用Cancel()方法来取消操作,但是为了演示方便,我们下面的例子使用的都是CancelAfter()来进行延迟关闭

🚀IsCancellationRequested

我们创建一个CancellationTokenSource对象,然后通过CancelAfter(5000)设置一个5秒的取消延迟。然后写一个无限循环,在循环中打印"任务执行中!"(👻假装在执行任务)!5秒钟后,CancelAfter方法会触发取消请求,这时cts.IsCancellationRequested属性会变为true。然后就会打印"任务被取消!",并跳出循环。如下图所示👇

    public static void Main(string[] args)
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        cts.CancelAfter(5000);
        while (true)
        {
            Console.WriteLine("任务执行中!");
            if (cts.IsCancellationRequested)
            {
                Console.WriteLine("任务被取消!");
                break;
            }
        }
    }

🚀ThrowIfCancellationRequested

将刚刚的代码修改一下,换成使用ThrowIfCancellationRequested(),方法执行后,还是会在控制台打印"任务执行中!",5秒钟后,CancelAfter方法触发取消请求,于是执行到ThrowIfCancellationRequested()的时候抛出了一个异常,操作被取消了!

    public static void Main(string[] args)
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        cts.CancelAfter(5000);
        while (true)
        {
            Console.WriteLine("任务执行中!");
            cts.Token.ThrowIfCancellationRequested();
        }
    }

🐤在控制器中使用

在ASP.NET Core中,CancellationToken是一个可选参数,可以被添加到控制器的动作方法中。当客户端请求被关闭或取消时,ASP.NET Core会自动取消关联的CancellationToken。

这是因为ASP.NET Core的内部机制。当客户端发送一个请求到服务器,服务器会为这个请求创建一个CancellationToken,并且当客户端关闭连接时,服务器会自动调用CancellationToken的Cancel方法,以便通知应用程序请求已经被取消。

因此,我们可以直接在Controller中加入CancellationToken参数,如下图👇,这是我的一个ai识别项目,他会将收到的图片作为请求体,调用我部署在服务器上的ai识别api,如果用户通过网页,上传了一张图片进行ai识别,但是因为识别时间太长了,他不想等待并且把网页关了,此时我的后台还在傻傻的进行图片识别,势必会造成资源的浪费,下面我们就来改造一下他!

在上面我们调用PutPhoto的时候参数中添加了controller中拿到的cancellationToken,因此这边方法中的参数也加上CancellationToken cancellationToken来接,如下图👇,上面的代码都是对请求体进行组装,我们重点看最下面这一行。

var response = await client.ExecuteAsync<PhotoRes>(request);

 🚀通过异步方法的参数使用cancellationToken

Ctrl + 左键 点击 ExecuteAsync

我们查看一下RestClient的ExecuteAsync方法,可以看见他是有一个可选参数cancellationToken,这意味这我们又可以直接把在controller中拿到的cancellationToken继续丢进去。

因此,我们把最后一句代码改成,然后我在执行这一行代码之前,打一个断点。

var response = await client.ExecuteAsync<PhotoRes>(request,cancellationToken);

 在执行这行代码之前,我将浏览器关闭了,然后再继续下一步

 我们在返回结果中看到,错误信息中提示:A task was canceled,一个任务被取消,其实哪怕是我的请求在进行中,只要一关闭浏览器,任务就会立马结束,但是因为我服务器的响应速度太快了,不好实现这个演示!

🚀api结合ThrowIfCancellationRequested()

假设你现在的场景中异步方法并没有cancellationToken参数,那么你可以结合我们上面演示中使用的ThrowIfCancellationRequested()来取消操作。请求取消时,它会抛出一个异常OperationCanceledException,这样你就可以在你的代码中捕获这个异常并进行相应的处理。

try
{
    var response = await client.ExecuteAsync<PhotoRes>(request);
    // 在这里检查取消标记
    cancellationToken.ThrowIfCancellationRequested();
}
catch (OperationCanceledException)
{
    // 这里处理取消操作的逻辑
}

要注意的是,这种方式只能取消还没有开始的操作。如果ExecuteAsync方法已经开始执行,那么这个取消请求就无法停止它,因此如果异步方法可以支持传参cancellationToken的话,我们还是首选使用传参的方法!


http://www.niftyadmin.cn/n/5032683.html

相关文章

【深入Java原子类:高性能并发编程的技巧与实践】

文章目录 1. 引言2. AtomicInteger详解2.1 性能测试对比2.2 AtomicInteger的基本用法2.2.1 AtomicInteger的创建2.2.2 AtomicInteger的Incremental操作2.2.3 AtomicInteger的Decremental操作2.2.4 原子性地更新值compareAndSet和weakCompareAndSetPlain区别❓❓❓ 2.2.5 Atomic…

Visual Studio2019报错

1- Visual Studio2019报错 错误 MSB8036 找不到 Windows SDK 版本 10.0.19041.0的解决方法 小伙伴们在更新到Visual Studio2019后编译项目时可能遇到过这个错误&#xff1a;“ 错误 MSB8036 找不到 Windows SDK 版本 10.0.19041.0的解决方法”&#xff0c;但是我们明明安装了该…

【Godot】解决游戏中的孤立/孤儿节点及分析器性能问题的分析处理

Godot 4.1 因为我在游戏中发现&#xff0c;越运行游戏变得越来越卡&#xff0c;当你使用 Node 节点中的 print_orphan_nodes() 方法打印信息的时候&#xff0c;会出现如下的孤儿节点信息 孤儿节点信息是以 节点实例ID - Stray Node: 节点名称(Type: 节点类型) 作为格式输出&a…

RHCSA_Linux 从命令行管理文件

目录 一、文件命令规范&#xff1a; 二、创建链接文件 1、创建软链接文件 2、创建硬链接文件 三、目录操作命令 1、创建目录 -- mkdir 2、统计目录及文件的空间占用情况 -- du 3、删除目录文件 四、创建、删除普通文件 1、创建普通文件 2、删除普通文件 五、数据流和…

2023icpc网络预选赛I. Pa?sWorD(dp)

题目给定字符串长度n以及字符串s 其中出现小写字母可以代表小写字母和大写字母 比如a可以代表a和A 出现?可以代表26个小写字母和26个大写字母和10个数字 出现大写字母和数字就是原本的数 同时要求大写字母&#xff0c;小写字母&#xff0c;数字一定都存在替换完的字符串中…

前端笔试2

1.下面哪一个是检验对象是否有一个以自身定义的属性? foo.hasOwnProperty("bar")bar in foo foo["bar"] ! undefinedfoo.bar ! null 解析&#xff1a; bar in foo 检查 foo 对象是否包含名为 bar 的属性&#xff0c;但是这个属性可以是从原型链继承来的&a…

Linux入门教程||Linux 用户和用户组管理

Linux系统是一个多用户多任务的分时操作系统&#xff0c;任何一个要使用系统资源的用户&#xff0c;都必须首先向系统管理员申请一个账号&#xff0c;然后以这个账号的身份进入系统。 用户的账号一方面可以帮助系统管理员对使用系统的用户进行跟踪&#xff0c;并控制他们对系统…

rust数组

一、定义数组 &#xff08;一&#xff09;一维数组 1.指定所有元素 语法格式 let variable_name: [dataType; size] [value1,value2,value3];例如 let arr: [i32; 4] [10,20,30,40];2.指定初始值和长度 所有元素具有相同的值 语法格式 let variable_name: [dataType; size…