.net 4.0 Asp.Net 4.0 CacheItemPolicy滑动过期不正确?

.net 4.0 Asp.Net 4.0 CacheItemPolicy滑动过期不正确?,.net-4.0,.net 4.0,可能原因是睡眠是不确定的。它不会在600毫秒内暂停线程。它会使线程暂停至少600毫秒。它很可能会在你没有意识到的情况下超过你设置的1秒滑动到期时间。我也有同样的问题。但实际上问题是@Colin说了什么。线程.Sleep正在接管超过一秒钟的时间 所以我做了一个延迟更大的测试 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Cachi

可能原因是睡眠是不确定的。它不会在600毫秒内暂停线程。它会使线程暂停至少600毫秒。它很可能会在你没有意识到的情况下超过你设置的1秒滑动到期时间。

我也有同样的问题。但实际上问题是@Colin说了什么。
线程.Sleep
正在接管超过一秒钟的时间

所以我做了一个延迟更大的测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Runtime.Caching;

using Xunit;

namespace Demo.Caching.Test
{
    class MemoryCacheManagerTest
    {
        [Fact]
        public void Test()
        {
            CacheItemPolicy policy = new CacheItemPolicy();
            policy.SlidingExpiration = TimeSpan.FromSeconds(1);

            MemoryCache.Default.Set("cacheKey4", 4, policy);
            Assert.Equal(4, MemoryCache.Default.Get("cacheKey4"));
            System.Threading.Thread.Sleep(600);
            Assert.Equal(4, MemoryCache.Default.Get("cacheKey4"));
            System.Threading.Thread.Sleep(600);
            Assert.Equal(4, MemoryCache.Default.Get("cacheKey4"));
            // Here I get error
            // Expected: 4, Actual: (null)

            System.Threading.Thread.Sleep(1000);
            Assert.Null(MemoryCache.Default.Get("cacheKey4"));
        }
    }
}
[TestMethod]
公众假期(
{
MemoryCache.Default.Add(“test”,1,
新缓存项策略
{
滑动过期=新的时间跨度(0,0,秒:5)
});
对于(int i=0;i<15;++i)
{
Assert.IsNotNull(MemoryCache.Default.Get(“test”);
睡眠(700);
}
}

就这样过去了。我不确定它是否会一直起作用——可能不会——但我只是确认了滑动确实起作用。

正如其他答案所说,这是不是,因为Thread.Sleep()花费的时间比预期的要长

MemoryCache
的滑动计时器似乎非常不精确。我猜这是为了避免锁定,并保持缓存的性能

  • 如果将滑动过期时间设置为1秒或更短,则缓存项将在1秒后被逐出,而不管它们被访问多少次
  • 在1到2秒之间,仍有可能逐出缓存项。这可能在某种程度上取决于计算机所承受的负载,并且在很大程度上取决于访问项目的时间,但不像您想象的那样可预测。例如:
    • 如果我将过期时间设置为1.001秒到1.24秒之间的任意值,并在两次访问之间休眠200或250毫秒,它会将该值保留在缓存中;但如果我睡眠201或249毫秒,该项目就会被逐出
    • 如果我将过期时间设置为1.25秒,我最多可以睡624毫秒而不会出现问题,但如果我达到625毫秒,则缓存项将被逐出
  • 一旦您达到2秒的到期时间,即使您仅在到期期限之前访问该项目一次,它似乎也能正常工作
所以我想教训是不要依赖滑动过期来正确处理2秒以下的值。这可能与
PollingInterval
设置为2秒有关

代码:

var span=TimeSpan.FromSeconds(1);//必要时改变
var sw=新秒表();
var cache=newmemorycache(“testcache”);
sw.Start();
Add(“test”,“hello”,newcacheitempolicy{SlidingExpiration=span});
控制台写入线(软件延迟毫秒);
对于(int i=0;i<40;i++)
{
Console.WriteLine(sw.elapsedmillesons+“:”+cache.Get(“测试”));
Thread.Sleep(50);//根据需要进行更改
}

关于代码的所有内容,问得好!另请参见@StripplingWarrior关于
PollingInterval
的回答。诀窍似乎是对低于轮询间隔的延迟进行了不精确的处理。
[TestMethod]
public void Sliding()
{
    MemoryCache.Default.Add("test", 1,
        new CacheItemPolicy
        {
            SlidingExpiration = new TimeSpan(0, 0, seconds: 5)
        });

    for (int i = 0; i < 15; ++i)
    {
        Assert.IsNotNull(MemoryCache.Default.Get("test"));
        Thread.Sleep(700);
    }
}
var span = TimeSpan.FromSeconds(1); // change as necessary
var sw = new Stopwatch();
var cache = new MemoryCache("testcache");
sw.Start();
cache.Add("test", "hello", new CacheItemPolicy{SlidingExpiration = span});
Console.WriteLine(sw.ElapsedMilliseconds);
for (int i = 0; i < 40; i++)
{
    Console.WriteLine(sw.ElapsedMilliseconds + ": " + cache.Get("test"));
    Thread.Sleep(50); // change as necessary
}