首页 > 编程语言 >在C#中使用 CancellationToken 处理异步任务

在C#中使用 CancellationToken 处理异步任务

时间:2024-03-17 15:55:05浏览次数:28  
标签:CancellationToken 异步 Console cts C# CancellationTokenSource Task

来源:在C#中使用 CancellationToken 处理异步任务 - 知乎 (zhihu.com)

在 .NET Core 中使用异步编程已经很普遍了, 你在项目中随处可见 async 和 await,它简化了异步操作,允许开发人员,使用同步的方式编写异步代码,你会发现在大部分的异步方法中,都提供了CancellationToken参数,本文主要介绍下 CancellationTokenSource 和 CancellationToken在异步任务中的使用。

 

 

手动取消任务

创建一个 CancellationTokenSource,然后调用异步方法时,传入 CancellationToken,它是一个轻量级对象,可以通知请求是否已取消,我们可以手动调用 cts.Cancel() 来取消任务,为了方面演示,这里我有用到局部方法。

static async Task Main(string[] args)
{
   async Task Execute(CancellationToken token)
   {
       await Task.Delay(3000, token);
       Console.WriteLine("Executed");
   } 

   CancellationTokenSource cts = new CancellationTokenSource();  

   _ = Execute(cts.Token);

   // 手动取消任务
   cts.Cancel();  

   Console.ReadKey();
}   

定时取消任务

创建 CancellationTokenSource 的时候,可以传入时间(毫秒或者Timespan), 通过它我们可以在等待一段时间后,自动取消任务。

CancellationTokenSource cts = new CancellationTokenSource(1000);  

_ = Execute(cts.Token);  

Console.ReadKey();

我们也可以调用 cts.CancelAfter(1000), 它会在1s后取消任务。

cts.CancelAfter(1000);

CancellationToken 注册回调

我们可以调用 Register()方法,注册Token取消的回调,参数需要传入 Action 委托。

CancellationTokenSource cts = new CancellationTokenSource(1000);

cts.Token.Register(() => Console.WriteLine("任务已取消!"));

// 开始异步任务
_ = Execute(cts.Token);    

Console.ReadKey();

Register() 注册回调后,返回一个 CancellationTokenRegistration 对象,同样的,你可以在回调函数执行前,移除注册回调,就像这样:

cts.Token.Register(() => Console.WriteLine("任务已取消!")).Unregister();

在 HttpClient 中使用

同样,你可以在 HttpClient 中使用传入 CancellationToken (或者使用HttpClient的Timeout属性),超时后,它会抛出一个 TaskCanceledException 的异常:

CancellationTokenSource cts = new CancellationTokenSource(10);  

_ = await new HttpClient().GetAsync("https://www.youtube.com/",cts.Token); 

Console.ReadKey();

在 WebAPI中使用

我创建了一个 WebAPI 项目,其中的控制器代码如下,等待了5s,然后进行输出信息。

[HttpGet]
public async Task<IActionResult> Index()
{
    await Task.Delay(5000);
    Console.WriteLine("Executed");
    return Ok();
}

启动项目后,我们在浏览器页面上访问接口,在第一次访问接口等待响应时,我刷新一次了页面,现在程序的输出信息如下:

 

 

说明前台页面刷新后,后台并没有做取消操作,执行了两次!

我们可以把程序改成这样,传入 CancellationToken

[HttpGet]
public async Task<IActionResult> Index(CancellationToken token)
{
    await Task.Delay(5000,token);
    Console.WriteLine("Executed");
    return Ok();
}

现在在浏览器访问页面,同样的,第一次还未返回是,我们刷新一次页面,程序输出如下:

 

 

只有一次输出,第一次请求抛出了一次 TaskCanceledException 异常,没有继续执行后边的逻辑,当然你可以捕获这个异常,返回更友好的提示!

标签:CancellationToken,异步,Console,cts,C#,CancellationTokenSource,Task
From: https://www.cnblogs.com/yibinboy/p/18078689

相关文章

  • C++20新特性-barrier
     以下内容由豆包大语言模型生成,内容仅供参考: C++20引入了一个新的标准库头文件 <barrier>,其中包含了对屏障(barrier)的支持。屏障是一种用于同步多个线程的同步原语,它允许线程在某个点上等待,直到所有线程都到达该点。C++20的 <barrier> 头文件提供了一个 std::barrier......
  • 实验1 C语言开发环境使用和数据类型、运算符、表达式
    ......
  • Clion输出中文乱码终极解决方案
    网上大部分方法是在编辑文件时将编码改成GBK,个人认为不太正确。现有一个终极解决的方案,不需要改成GBK。 保存关闭后,按住Ctrl+Shift+Alt+/(不够快捷的快捷键…)选中Registry… 然后取消run.processes.with.pty然后就可以了~ ......
  • 452. 用最少数量的箭引爆气球c
    typedefstructnode{intleft;intright;}bounds;intcmp(constvoid*a,constvoid*b){bounds*x=(bounds*)a;bounds*y=(bounds*)b;if(x->right>y->right)return1;return-1;}intfindMinArrowShots(int**points,intp......
  • 【经验】关于c++11中string类型字符串和整形相互转化的用法
    https://blog.csdn.net/Elephant_King/article/details/129225134 c++11中为我们提供了许多非常方便的函数,可以帮助我们在整形与string类型字符串进行转换关于Dev-c++如何使用c++11,因为本人是mac系统,使用cLion,无法安装Dev,可以在网上搜其他教程实现整形转字符串(to_string())to_s......
  • 《A ConvNet for the 2020s》阅读笔记
    论文标题《AConvNetforthe2020s》面向2020年代的ConvNet作者ZhuangLiu、HanziMao、Chao-YuanWu、ChristophFeichtenhofer、TrevorDarrell和SainingXie来自FacebookAIResearch(FAIR)和加州大学伯克利分校初读摘要“ViT盛Conv衰”的现状:视觉识......
  • CSS常见选择器
    1.基础选择器   选择器作用:查找标签设置样式标签选择器:使用标签名作为选择器类选择器:(1)定义类选择器-->.类名(2)使用类选择器标签添加class="类名"<style>/*定义*/.green{color:green;}.size{font-size:10px;}<......
  • 常见排序算法(C/C++)--- 动画演示
        本篇将介绍一些常见的排序算法,如插入排序:直接插入排序、希尔排序;选择排序:选择排序、堆排序;交换排序:快速排序、冒泡排序;以及最后的归并排序。    对于以上的排序算法,我们总结了每种排序算法的特性,接着对直接插入排序进行了优化;然后实现了归并排序和快速排......
  • CSS——字体和文本样式
    1.字体样式1.1.字体大小属性名:font-size取值:数字+px注意点:谷歌浏览器默认文字大小是16px单位需要设置,否则无效1.2.字体粗细属性名:font-weight取值:关键字:正常normal加粗bold纯数字:100~900的整百数:正常400加粗700注意点:不是所有字体都提供了......
  • VCTF-Forensics
    这个取证有点意思,也没有套太多。下载附件,直接FTK打开,我们发现两个分区,其中一个又hint.zip和一个图片,发现里面图片一致,一眼丁真明文攻击:打开见key:直接PasswordkitForensics开梭:然后FTK继续开,找到flag.txt,里面是个字符串,一眼十六进制转出摩斯密码:解密,是个奶牛快传:......