ASP.net Cache Absolute Expiration not working

I am storing a single integer value in HttpContext.Cache with an absolute expiration time of 5 minutes from now. However, after waiting 6 minutes (or longer), the integer value is still in the Cache (ie it's never removed even though the absolute expiration has passed). Here is the code I am using:

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;
    }
}

The first time I run UpdateCountFor("127.0.0.1") it inserts 1 into the cache with key "127.0.0.1" and an absolute expiration of 5 minutes from now as expected. Every subsequent run then increments the value in the cache. However, after waiting 10 minutes it continues to increment the value in the Cache. The value never expires and never gets removed from the Cache. Why is that?

It's my understanding that an absolute expiration time means the item will get removed approximately at that time. Am I doing something wrong? Am I misunderstanding something?

I'm expecting the value to be removed from the Cache after 5 minutes time, however it stays in there until I rebuild the project.

This is all running on .NET 4.0 on my local machine.


It turns out that this line:

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

removes the previous value and re-inserts the value with NO absolute or sliding expiration time. In order to get around this I had to create a helper class and use it like so:

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);
}

This will get around the issue and let the counter properly expire at the absolute time while still enabling updates to it.


Try using DateTime.UtcNow to calculate your timeout period instead of datetime.Now . You may be running into the issue described below:

absoluteExpiration Type: System.DateTime The time at which the inserted object expires and is removed from the cache. To avoid possible issues with local time such as changes from standard time to daylight saving time, use UtcNow rather than Now for this parameter value. If you are using absolute expiration, the slidingExpiration parameter must be NoSlidingExpiration.


There's a simpler answer than what smoak posted. Using that example as a starting point, the updated code below works and doesn't require a re-insert. The reason this works is because classes are reference types. Thus, when you update the counter inside the class instance it doesn't cause the cache to trigger an update.

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++;
    }
}
链接地址: http://www.djcxy.com/p/62992.html

上一篇: R中的缓存/记忆/散列选项

下一篇: ASP.net缓存绝对过期不起作用