查看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);
}一旦TimeSpan完成,它就会显示出对象被弹出的行为,无论对象是否已被访问。Linq查询在enumerable.Last();语句处执行,此时它只会在缓存未过期时使用。一旦停止,列表中的最后一项将指示该项在缓存中的驻留时间。
这个问题是关于MemoryCache的行为的。不是linq查询。
这是其他人的期望吗(也就是说,每次触摸都不会滑到到期时间)?是否有一种模式可以延长被“触摸”对象的生存期?
即使我在缓存中编写了一个包装器,并且每次检索对象时都会将对象重新添加到缓存中,但我发现了更新,而另一个SlidingExpiration它仍然只遵守初始设置。为了让它按照我想要的方式工作,在重新添加它之前,我必须物理地将它从缓存中删除!这可能会在多线程环境中造成不理想的竞争条件。
发布于 2016-12-30 15:14:04
... new CacheItemPolicy {SlidingExpiration = TimeSpan.FromSeconds(1) }这在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);
}
}
}CacheExpires.MIN_UPDATE_DELTA是关键,它阻止调用UtcUpdate()。或者换一种说法,在更新滑动计时器之前,至少要经过MIN_UPDATE_DELTA一段时间。引用源没有对CacheExpired类进行索引,这表明它们对它的工作方式并不完全满意:),但是一个像样的反编译器可以向您展示:
static CacheExpires()
{
MIN_UPDATE_DELTA = new TimeSpan(0, 0, 1);
MIN_FLUSH_INTERVAL = new TimeSpan(0, 0, 1);
// etc...
}换句话说,硬编码为1秒。现在没有办法改变它,这太丑了。这个测试程序中的SlidingExpiration值需要1.2秒,因为Thread.Sleep( 100 )实际上不会休眠100毫秒,它需要更多的时间。换句话说,它将是第11个Get()调用,它可以让滑动计时器在这个测试程序中滑动。你没走那么远。
嗯,这应该被记录下来,但我想这是有可能改变的。现在,您需要假设实际的滑动到期时间应该至少为2秒。
https://stackoverflow.com/questions/41395490
复制相似问题