首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SlidingExpiration和MemoryCache

SlidingExpiration和MemoryCache
EN

Stack Overflow用户
提问于 2016-12-30 11:23:57
回答 1查看 9.4K关注 0票数 27

查看MemoryCache的文档,我希望如果在Expiration期间访问了一个对象,那么这个时间段将被刷新。老实说,我想我是从“滑动”这个名字中推断出来的。

但是,从这个测试中可以看出

代码语言:javascript
复制
   [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它仍然只遵守初始设置。为了让它按照我想要的方式工作,在重新添加它之前,我必须物理地将它从缓存中删除!这可能会在多线程环境中造成不理想的竞争条件。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-12-30 15:14:04

代码语言:javascript
复制
 ... new CacheItemPolicy {SlidingExpiration = TimeSpan.FromSeconds(1) }

这在MSDN中没有得到充分的记录。你有点不走运,1秒还不够。一根头发,用2秒,你就会看到它像你希望的那样工作。修改一下FromMilliseconds(),您将看到在这个程序中,~1.2秒是快乐的最小值。

解释这是相当复杂的,我必须讨论MemoryCache如何避免每次访问缓存时都必须更新滑动计时器。就像你想象的那样,这是相对昂贵的。让我们走一条捷径,带您去相关的参考源代码。小到可以粘贴在这里:

代码语言:javascript
复制
    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类进行索引,这表明它们对它的工作方式并不完全满意:),但是一个像样的反编译器可以向您展示:

代码语言:javascript
复制
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秒。

票数 57
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41395490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档