暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

ASP.NET Core之CancellationToken中断请求

356

    如果一个Controller.Action里的处理非常耗时,比如读数据库、文件操作、调用第三方接口等
此时用户随时可能关闭浏览器、F5刷新网页等操作。
但是服务端的耗时代码任然在执行,这太浪费了,既然用户终止请求了,我们就应该取消所有的耗时操作

    在.net开发中,几乎所有的异步方法都有个CancellationToken类型的参数,只要我们传入此令牌,将来我们随时可以通过此令牌取消异步操作
而asp.net中HttpContext提供了一个RequestAborted属性,它就是CancellationToken类型,当用户以任何方式终止请求时, HttpContext.RequestAborted就会触发取消
所以如果我们在异步方法中都传入这个参数,就能实现当用户终止请求时,我们所有的异步操作都会立即取消。

并发大的情况下,这个操作很重要。


幸好,ASP.NET Core开发团队体贴的考虑了这一点,允许我们通过以下两种方式来获取客户端的请求是否被终止。

  1. 通过HttpContex
    RequestAborted
    属性:

  2. 通过方法注入CancellationToken
    参数:


if (HttpContext.RequestAborted.IsCancellationRequested)

{
can stop working now

}


[HttpGet]

public async Task<ActionResult> GetHardWork(CancellationToken cancellationToken)
{
...

if (cancellationToken.IsCancellationRequested)
{
stop!
}

...

}



上面是asp.net默认行为,你会发现一个问题,真个应用程序有铺天盖地的异步方法,如果都想实现上述特征 我们所有的异步方法都得加上CancellationToken参数
abp提供了一种牛X的方式
它提供一个ICancellationTokenProvider接口,它会为我们提供一个CancellationToken对象,所以我们定义的异步方法不需要定义CancellationToken参数了,首先在我们的类中依赖注入这个接口,然后在调用.net内置库或第三方库的异步方法时,传入ICancellationTokenProvider.Token就可以了,如下:

1 ICancellationTokenProvider CancellationTokenProvider ;
2
3 //构造函数注入CancellationTokenProvider 略...
4
5 public override async Task<List<TEntity>> GetAllListAsync()
6 {
7 return await GetAll().ToListAsync(CancellationTokenProvider.Token);
8 }


比较推荐的是使用“空模式”,用属性注入,如下:

1 public ICancellationTokenProvider CancellationToken { get; set; } = NullCancellationTokenProvider.Instance;

abp中最终使用的是HttpContextCancellationTokenProvider,它的Token属性返回的就是HttpContext.RequestAborted


默认情况下abp的Repository中的所有异步方法已经使用这种模式,由于我们开发是大部分情况下都是数据库读写,所以我们在abp中几乎可以不关心这事,默认就是以合理的方式运行的。


参考文章:

https://www.jianshu.com/p/9988f2a27f8d

https://www.cnblogs.com/jionsoft/p/12727836.htm


文章转载自跟着阿笨一起玩NET,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论