查看MemoryCache的文档,我预计如果在Expiration期间访问了一个对象,则会刷新该期间.说实话,我认为我从"滑动"这个名称推断出的东西和任何东西一样多.
但是,从这个测试看来
[Test]
public void SlidingExpiryNotRefreshedOnTouch()
{
var memoryCache = new MemoryCache("donkey")
{
{
"1",
"jane",
new CacheItemPolicy {SlidingExpiration = TimeSpan.FromSeconds(1) }
}
};
var enumerable = Enumerable.Repeat("1", 100)
.TakeWhile((id, index) =>
{
Thread.Sleep(100);
return memoryCache.Get(id) != null; // i.e. it still exists
})
.Select((id, index) => (index+2)*100.0/1000); // return the elapsed time
var expires = enumerable.Last(); // gets the last existing entry
expires.Should().BeGreaterThan(1.0);
}
Run Code Online (Sandbox Code Playgroud)
它失败并显示一旦TimeSpan完成后对象被弹出的行为,无论对象是否已被访问.Linq查询在enumerable.Last()中执行; 语句,此时缓存尚未过期.一旦停止,列表中的最后一项将指示项目在缓存中存在多长时间.
对于Clarity这个问题是关于MemoryCache的行为.不是linq查询.
这是否是其他人的期望(即每次触摸时过期不会滑动)?是否有一种模式可以延长"触摸"对象的生命周期?
更新我发现即使我在缓存周围写了一个包装器,并且每次检索它时都将对象重新添加回缓存,而另一个SlidingExpiration仍然只支持初始设置.为了让它以我想要的方式工作,我必须在重新添加它之前将其从缓存中删除!这可能在多线程环境中导致不期望的竞争条件.
Han*_*ant 37
... new CacheItemPolicy {SlidingExpiration = TimeSpan.FromSeconds(1) }
Run Code Online (Sandbox Code Playgroud)
这在MSDN中没有充分记录.你有点不走运,1秒还不够.通过头发,使用2秒,你会看到它的工作方式就像你希望的那样.使用FromMilliseconds()修补更多内容,你会发现~1.2秒是这个程序中最开心的.
解释这个问题相当复杂,我不得不谈谈MemoryCache如何避免每次访问缓存时都必须更新滑动计时器.正如您可能想象的那样,这是相对昂贵的.让我们走捷径,带您到相关的参考源代码.小到足以粘贴在这里:
internal void UpdateSlidingExp(DateTime utcNow, CacheExpires expires) {
if (_slidingExp > TimeSpan.Zero) {
DateTime utcNewExpires = utcNow + _slidingExp;
if (utcNewExpires - _utcAbsExp >= CacheExpires.MIN_UPDATE_DELTA || utcNewExpires < _utcAbsExp) {
expires.UtcUpdate(this, utcNewExpires);
}
}
}
Run Code Online (Sandbox Code Playgroud)
CacheExpires.MIN_UPDATE_DELTA是关键,它阻止调用UtcUpdate().换句话说,至少MIN_UPDATE_DELTA值的时间必须通过才会更新滑动计时器.CacheExpired类没有被Reference Source索引,暗示他们对它的工作方式并不完全满意:)但是一个体面的反编译器可以告诉你:
static CacheExpires()
{
MIN_UPDATE_DELTA = new TimeSpan(0, 0, 1);
MIN_FLUSH_INTERVAL = new TimeSpan(0, 0, 1);
// etc...
}
Run Code Online (Sandbox Code Playgroud)
换句话说,硬编码为1秒.现在无法改变它,这非常难看.此测试程序中的SlidingExpiration值需要大约1.2秒,因为Thread.Sleep(100)实际上不会休眠100毫秒,需要更多时间.换句话说,它将是第11个Get()调用,它使滑动计时器在此测试程序中滑动.你没那么远.
嗯,这应该记录在案,但我猜这可能会有所改变.现在,您需要假设一个实际的滑动到期时间应该至少为2秒.
| 归档时间: |
|
| 查看次数: |
4575 次 |
| 最近记录: |