Asp.net core CancellationToken vs CancellationChangeToken
Asp.net core CancellationToken vs CancellationChangeToken,asp.net-core,.net-core,cancellation-token,Asp.net Core,.net Core,Cancellation Token,CancellationToken和CancellationChangeToken之间有什么区别?我什么时候用哪一种 似乎它们可以用于同样的目的。我缺少什么?CancellationChangeToken实现了IChangeToken,它的构造函数采用了一个CancellationToken参数 我想说的是,它能够在使用相同的令牌时,同时使用期望IChangeToken的方法和期望CancellationToken的方法 下面是一个来自 var firstCancellationTokenSou
CancellationToken
和CancellationChangeToken
之间有什么区别?我什么时候用哪一种
似乎它们可以用于同样的目的。我缺少什么?
CancellationChangeToken
实现了IChangeToken
,它的构造函数采用了一个CancellationToken
参数
我想说的是,它能够在使用相同的令牌时,同时使用期望IChangeToken
的方法和期望CancellationToken
的方法
下面是一个来自
var firstCancellationTokenSource=新的CancellationTokenSource();
var secondCancellationTokenSource=新的CancellationTokenSource();
var firstCancellationToken=firstCancellationTokenSource.Token;
var secondCancellationToken=secondCancellationTokenSource.Token;
var firstCancellationChangeToken=新的CancellationChangeToken(firstCancellationToken);
var secondCancellationChangeToken=新的CancellationChangeToken(secondCancellationToken);
var compositeChangeToken=
新CompositeChangeToken(
新名单
{
firstCancellationChangeToken,
secondCancellationChangeToken
});
在这里,构造函数获取IChangeToken
列表的CompositeChangeToken
,用两个CancellationToken
实例化。如果没有CancellationChangeToken
类,这是不可能的。简短回答:
CancellationChangeToken
是CancellationToken
的薄包装,它通过HasChanged
属性公开令牌的取消状态
由于CancellationChangeToken
实现了IChangeToken
接口,因此它可以传递给对令牌更改做出反应的任何对象,例如IMemoryCache
:每个缓存项都可以设置为在一组特定条件下过期,这些条件由IChangeToken
实例抽象。例如,这些条件可能是配置更改,或用户的显式无效请求
CancellationChangeToken
包装可以传递给一个或多个缓存项,以便在取消时将它们逐出。开发者也可以决定直接使用CancellationToken
;然而,与通过IChangeToken
进行的抽象相比,这将使内部逻辑和外部API变得复杂,因为IChangeToken非常干净、可扩展,并且工作正常
长答覆: 接口
IChangeToken
定义跟踪某种令牌的方法,检查它是否已更改(HasChanged
),并可能在更改后自动触发一些回调
IChangeToken
有多种实现方式;例如,它们跟踪文件或配置选项
CancellationChangeToken
的作用是什么
A快速显示CancellationChangeToken
是一个精简的IChangeToken
包装CancellationToken
:
public bool HasChanged=>Token.iscancellationrequest;
因此,其“更改”状态直接对应于基础令牌的取消状态
乍一看,这似乎很奇怪:一个CancellationToken
已经存在,那么为什么要引入一个公开更少功能的包装器呢
实际上,至少有一个用例需要一种观察令牌状态的抽象方法:
缓存
NET内核提供了不同的缓存方式;这里我将使用它作为一个例子,它提供了一个简单的基于内存的键/值缓存,并且可以用最少的努力来使用
为了减少每个请求对性能的影响,缓存频繁需要的、昂贵的计算是有意义的。但是,我们需要一种跟踪活动缓存项的方法,以便在它们过时时立即将其逐出。问题是,缓存项可能具有非常不同的过时条件,例如,它们取决于配置值或本地文件(并且需要在这些配置值或本地文件更改后立即更新),或者具有定期超时
IChangeToken
接口提供了一种简单的方法来抽象这些逐出条件,这样缓存只需检查给定的IChangeToken
对象的状态,而不必直接查看文件、计时器等。缓存甚至可能注册回调,这样令牌状态的更改直接触发逐出逻辑,因此不需要轮询
回到我们的CancellationChangeToken
CancellationToken
允许设置延迟,直到它被自动取消,因此在使用CancellationChangeToken
包装它之后,我们可以将其传递到缓存条目以进行自动逐出:
public IActionResult Index()
{
if(!\u memoryCache.TryGetValue(“entry1”,out DateTime cachedValue))
{
cachedValue=DateTime.Now;
var cacheOptions=new MemoryCacheEntryOptions()
.AddExpirationToken(新的CancellationChangeToken(新的CancellationTokenSource(5000).Token));
_memoryCache.Set(“entry1”,cachedValue,cacheOptions);
}
返回视图(“索引”,cachedValue);
}
在本例中,我们缓存当前时间戳。5秒后,取消令牌被取消,时间戳被收回
但是,这还不能证明使用CancellationToken
是合理的,因为IMemoryCache
已经提供了一种通过设置过期时间的方法
现在我们了解了基于代币的驱逐的真正优势:我们可以
- 将多个
实例合并为一个,从而在这些实例中的任何一个发生更改时退出缓存项IChangeToken
- 使用相同的令牌
var firstCancellationTokenSource = new CancellationTokenSource(); var secondCancellationTokenSource = new CancellationTokenSource(); var firstCancellationToken = firstCancellationTokenSource.Token; var secondCancellationToken = secondCancellationTokenSource.Token; var firstCancellationChangeToken = new CancellationChangeToken(firstCancellationToken); var secondCancellationChangeToken = new CancellationChangeToken(secondCancellationToken); var compositeChangeToken = new CompositeChangeToken( new List<IChangeToken> { firstCancellationChangeToken, secondCancellationChangeToken });