ASP.net缓存绝对到期不起作用

时间:2011-05-05 18:08:46

标签: asp.net caching asp.net-mvc-3 c#-4.0

我在HttpContext.Cache中存储一个整数值,其绝对到期时间为5分钟。但是,在等待6分钟(或更长时间)之后,整数值仍然在缓存中(即,即使绝对过期已经过去,它也永远不会被删除)。这是我正在使用的代码:

public void UpdateCountFor(string remoteIp)
{
    // only returns true the first time its run
    // after that the value is still in the Cache
    // even after the absolute expiration has passed
    // so after that this keeps returning false
    if (HttpContext.Current.Cache[remoteIp] == null)
    {
        // nothing for this ip in the cache so add the ip as a key with a value of 1
        var expireDate = DateTime.Now.AddMinutes(5);
        // I also tried:
        // var expireDate = DateTime.UtcNow.AddMinutes(5); 
        // and that did not work either.
        HttpContext.Current.Cache.Insert(remoteIp, 1, null, expireDate, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
    }
    else
    {
        // increment the existing value
        HttpContext.Current.Cache[remoteIp] = ((int)HttpContext.Current.Cache[remoteIp]) + 1;
    }
}

我第一次运行UpdateCountFor(“127.0.0.1”)时,它会使用键“127.0.0.1”将1插入缓存,并且从现在起按预期的5分钟绝对到期。然后,每次后续运行都会增加缓存中的值。但是,等待10分钟后,它会继续增加Cache中的值。该值永不过期,永远不会从缓存中删除。那是为什么?

我的理解是,绝对到期时间意味着该项目将在当时被删除。难道我做错了什么?我误解了什么吗?

我希望在5分钟后将值从缓存中删除,但是在我重建项目之前它会保留在那里。

这一切都在我本地计算机上的.NET 4.0上运行。

3 个答案:

答案 0 :(得分:15)

事实证明这一行:

HttpContext.Current.Cache[remoteIp] = ((int)HttpContext.Current.Cache[remoteIp]) + 1;

删除以前的值,并使用NO绝对或滑动到期时间重新插入该值。为了解决这个问题,我必须创建一个帮助器类,并像这样使用它:

public class IncrementingCacheCounter
{
    public int Count;
    public DateTime ExpireDate;
}

public void UpdateCountFor(string remoteIp)
{
    IncrementingCacheCounter counter = null;
    if (HttpContext.Current.Cache[remoteIp] == null)
    {
        var expireDate = DateTime.Now.AddMinutes(5);
        counter = new IncrementingCacheCounter { Count = 1, ExpireDate = expireDate };
    }
    else
    {
        counter = (IncrementingCacheCounter)HttpContext.Current.Cache[remoteIp];
        counter.Count++;
    }
    HttpContext.Current.Cache.Insert(remoteIp, counter, null, counter.ExpireDate, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
}

这将解决问题并让计数器在绝对时间正常到期,同时仍然启用更新。

答案 1 :(得分:4)

尝试使用DateTime.UtcNow来计算超时时间而不是datetime.Now。您可能遇到了下述问题:

  

absoluteExpiration类型:   System.DateTime 时间   插入的对象过期并被删除   从缓存。 为了避免可能   与当地时间有关的问题,例如变化   从标准时间到夏令时   时间,使用UtcNow而不是Now   此参数值。如果您正在使用   绝对期满,   slidingExpiration参数必须是   NoSlidingExpiration。

答案 2 :(得分:0)

有一个比smoak发布的更简单的答案。使用该示例作为起点,下面的更新代码可以工作,不需要重新插入。这样做的原因是因为类是引用类型。因此,当您更新类实例中的计数器时,它不会导致缓存触发更新。

public class IncrementingCacheCounter
{
    public int Count;
}

public void UpdateCountFor(string remoteIp)
{
    IncrementingCacheCounter counter = null;
    if (HttpContext.Current.Cache[remoteIp] == null)
    {
        counter = new IncrementingCacheCounter { Count = 1};
        HttpContext.Current.Cache.Insert(remoteIp, counter, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
    }
    else
    {
        counter = (IncrementingCacheCounter)HttpContext.Current.Cache[remoteIp];
        counter.Count++;
    }
}