我在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上运行。
答案 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++;
}
}