经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » ASP.net » 查看文章
.NET Core使用 CancellationToken 取消API请求
来源:cnblogs  作者:chester·chen  时间:2024/3/18 15:05:01  对本文有异议

您是否曾经访问过一个网站,它需要很长时间加载,最终你敲击 F5 重新加载页面。

即使用户刷新了浏览器取消了原始请求,而对于服务器来说,API也不会知道它正在计算的值将在结束时被丢弃,刷新五次,服务器将触发 5 个请求。

为了解决这个问题,ASP.NET Core 为 Web 服务器提供了一种机制,就是CancellationToken.

用户取消请求时,你可以使用HttpContext.RequestAborted访问,您也可以使用依赖注入将其自动注入到您的操作中。

 

长时间运行的任务请求

现在我们假设您有一个 API 操作,在向用户发送响应之前可能需要一些时间才能完成。

在处理该操作时,用户可以直接取消请求,或刷新页面(这会有效地取消原始请求,并启动新请求)。

  1. [HttpGet(Name = "get")]
  2. public async Task<string> GetAsync()
  3. {
  4. try
  5. {
  6. _logger.LogInformation("request in");
  7. await Task.Delay(5 * 1000);
  8. _logger.LogInformation("request end");
  9. }
  10. catch (Exception ex)
  11. {
  12. _logger.LogInformation("request ex");
  13. }
  14. return "ok";
  15. }

如果用户在请求中途刷新浏览器,那么浏览器永远不会收到第一个请求的响应,但在server端可以看到,操作方法执行完成两次。

这是否是正确将取决于您的应用程序。

如果请求修改某些业务的状态,那么您可能不希望在方法中途停止执行。如果请求没有副作用,那么您可能希望尽快停止(可能很昂贵)操作。

用户取消请求时,你可以使用HttpContext.RequestAborted访问,您也可以使用依赖注入将其自动注入到您的操作中。

 

CancellationTokens取消不必要的请求

以下代码显示了如何通过将 CancellationTokenSource 注入到操作方法中,并通过其取消不必要的操作。

  1. [HttpGet(Name = "get")]
  2. public async Task<string> GetAsync(CancellationToken cancellationToken)
  3. {
  4. try
  5. {
  6. _logger.LogInformation("request in");
  7. await Task.Delay(5 * 1000,cancellationToken);
  8. _logger.LogInformation("request end");
  9. }
  10. catch (Exception ex)
  11. {
  12. _logger.LogInformation("request ex");
  13. }
  14. return "ok";
  15. }

通过这个改变,我们可以再次测试我们的场景。

我们发出一个初始请求,然后我们重新加载页面。正如您从下面的日志中看到的,第一个请求不会继续执行。

用户刷新浏览器取消请求后不久,原始请求就会中止,并TaskCancelledException通过 API 过滤器管道传播回来,并备份中间件管道。

根据您的场景,您可能能够依靠此类框架方法来检查 的状态CancellationToken,或者您可能需要自己监视取消请求。

 

过滤器捕获异常

您可以通过以上try catch 捕获,或者通过一个过滤器统一监视此异常。

  1. public class OperationCancelledExceptionFilter : ExceptionFilterAttribute
  2. {
  3. private readonly ILogger _logger;
  4. public OperationCancelledExceptionFilter(ILoggerFactory loggerFactory)
  5. {
  6. _logger = loggerFactory.CreateLogger<OperationCancelledExceptionFilter>();
  7. }
  8. public override void OnException(ExceptionContext context)
  9. {
  10. if (context.Exception is OperationCanceledException)
  11. {
  12. _logger.LogInformation("Request was cancelled");
  13. context.ExceptionHandled = true;
  14. context.Result = new StatusCodeResult(400);
  15. }
  16. }
  17. }
  18. builder.Services.AddControllers(options =>
  19. {
  20. options.Filters.Add<OperationCancelledExceptionFilter>();
  21. });

 

原文链接:https://www.cnblogs.com/chenyishi/p/18075600

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号