若是一个Controller.Action里的处理很是耗时,好比读数据库、文件操做、调用第三方接口等
此时用户随时可能关闭浏览器、F5刷新网页等操做。
可是服务端的耗时代码任然在执行,这太浪费了,既然用户终止请求了,咱们就应该取消全部的耗时操做git
在.net开发中,几乎全部的异步方法都有个CancellationToken类型的参数,只要咱们传入此令牌,未来咱们随时能够经过此令牌取消异步操做
而asp.net中HttpContext提供了一个RequestAborted属性,它就是CancellationToken类型,当用户以任何方式终止请求时, HttpContext.RequestAborted就会触发取消
因此若是咱们在异步方法中都传入这个参数,就能实现当用户终止请求时,咱们全部的异步操做都会当即取消github
并发大的状况下,这个操做很重要。数据库
参考代码:浏览器
1 public async Task<ActionResult> TestAsync() 2 { 3 await System.IO.File.ReadAllTextAsync(@"d:\a.txt", HttpContext.RequestAborted); 4 //....略
上面是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 }
比较推荐的是使用“空模式”,用属性注入,以下:asp.net
1 public ICancellationTokenProvider CancellationToken { get; set; } = NullCancellationTokenProvider.Instance;
abp中最终使用的是HttpContextCancellationTokenProvider,它的Token属性返回的就是HttpContext.RequestAborted异步
默认状况下abp的Repository中的全部异步方法已经使用这种模式,因为咱们开发是大部分状况下都是数据库读写,因此咱们在abp中几乎能够不关心这事,默认就是以合理的方式运行的。
但有时候咱们须要作其它异步操做,好比调用第三方接口啥的,此时就须要经过上面的方式来实现这种 用户取消请求则因此异步操做理解取消的效果。async
在某些场景中咱们可能并不想用这种默认的行为,而是但愿传入本身的CancellationToken对象,而不是用HttpContext的。这是我估计ICancellationTokenProvider.Use就派上用场了。怎么用呢?ide