sat*_*ite 8 cancellation-token .net-core asp.net-core
CancellationToken和之间有什么区别CancellationChangeToken?我什么时候使用哪一个?
似乎它们可以用于相同的目的。我缺少什么?
Jan*_*ann 13
CancellationChangeToken是 的一个薄包装CancellationToken,它通过属性公开令牌的取消状态HasChanged。
由于CancellationChangeToken实现了该IChangeToken接口,因此可以将其传递给对令牌更改做出反应的任何对象,例如IMemoryCache:每个缓存条目都可以设置为在一组特定条件下过期,这些条件是由IChangeToken实例抽象的。例如,这些条件可以是配置更改或用户的显式无效请求。
包装CancellationChangeToken器可以传递给一个或多个缓存条目,以便在取消时将它们逐出。开发人员也可以决定直接采取CancellationToken;IChangeToken然而,与非常干净、可扩展且工作良好的抽象相比,这会使内部逻辑和外部 API 变得复杂。
IChangeTokenIChangeToken定义了一种方法来跟踪某种令牌,检查它是否已更改(HasChanged),并可能在更改后自动触发一些回调。
有多种实现IChangeToken;例如,它们跟踪文件或配置选项。
CancellationChangeToken是查看源代码很快就会发现它CancellationChangeToken是一个薄IChangeToken包装CancellationToken:
public bool HasChanged => Token.IsCancellationRequested;
因此,其“已更改”状态直接对应于底层代币的取消状态。
乍一看,这似乎很奇怪: ACancellationToken已经提供了对注册自动回调的支持,那么为什么要引入一个公开更少功能的包装器呢?
嗯,实际上至少有一个用例需要一种观察令牌状态的抽象方法:
ASP.NET Core 提供了不同的缓存方式;我将IMemoryCache在这里用作示例,它提供了一个简单的内置基于内存的键/值缓存,并且可以轻松使用。
为了减少每个请求的性能影响,缓存经常需要的、昂贵的计算是有意义的。然而,我们需要一种方法来跟踪活动的缓存条目,以便在它们过时时立即将其驱逐。问题是,缓存条目可能具有非常不同的过时条件,例如它们取决于配置值或本地文件(并且一旦这些配置值或本地文件发生更改就需要更新),或者有定期超时。
该IChangeToken接口提供了一种简单的方法来抽象这些逐出条件,这样缓存只需检查给定IChangeToken对象的状态,而不是直接监视文件、计时器等。缓存甚至可能注册一个回调,这样令牌状态的变化会直接触发驱逐逻辑,因此不需要轮询。
CancellationChangeTokenACancellationToken允许设置一个延迟,直到它被自动取消,所以用 a 包装它之后CancellationChangeToken,我们可以将它传递给缓存条目以进行自动驱逐:
public IActionResult Index()
{
    if(!_memoryCache.TryGetValue("entry1", out DateTime cachedValue))
    {
        cachedValue = DateTime.Now;
        var cacheOptions = new MemoryCacheEntryOptions()
            .AddExpirationToken(new CancellationChangeToken(new CancellationTokenSource(5000).Token));
        _memoryCache.Set("entry1", cachedValue, cacheOptions);
    }
    return View("Index", cachedValue);
}
在此示例中,我们缓存当前时间戳。5 秒后,取消令牌被取消,并且时间戳被驱逐。
然而,这还不能证明使用 a 是合理的CancellationToken,因为IMemoryCache已经提供了一种通过 来设置过期时间的方法MemoryCacheEntryOptions。
现在我们了解基于代币驱逐的真正优势:我们可以
IChangeToken实例合并为一个CompositeChangeToken,一旦这些实例中的任何一个发生更改,就会逐出缓存条目。后一种情况对我们来说特别有趣:一些缓存条目可能相互依赖,因此当其中一个条目无效时,我们可能希望驱逐所有条目。这可以通过为CancellationToken它们的值分配一个shared ,并CancellationChangeToken为条目本身分配一个对应的a来实现。一旦缓存的值之一注意到它已经过时(例如,通过应用程序的其他部分轮询),它就会取消令牌。取消会传播到跟踪相应更改令牌的所有缓存条目,从而立即使它们全部无效。
| 归档时间: | 
 | 
| 查看次数: | 2834 次 | 
| 最近记录: |