2011-05-05 9 views
14

Estoy almacenando un único valor entero en HttpContext.Cache con un tiempo de caducidad absoluto de 5 minutos a partir de ahora. Sin embargo, después de esperar 6 minutos (o más), el valor entero aún está en la memoria caché (es decir, nunca se elimina aunque la expiración absoluta haya pasado). Aquí está el código que estoy utilizando:Caché ASP.AP absoluta caducidad no funciona

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

La primera vez que funciono UpdateCountFor ("127.0.0.1") se inserta 1 en la caché con la tecla "127.0.0.1" y una caducidad absoluta de 5 minutos a partir de ahora como se esperaba. Cada ejecución posterior luego incrementa el valor en la memoria caché. Sin embargo, después de esperar 10 minutos, continúa incrementando el valor en la caché. El valor nunca expira y nunca se elimina de la memoria caché. ¿Porqué es eso?

Tengo entendido que un tiempo de caducidad absoluto significa que el artículo será eliminado aproximadamente en ese momento. ¿Estoy haciendo algo mal? ¿Estoy malentendiendo algo?

Espero que el valor se elimine de la memoria caché después de 5 minutos, sin embargo, permanece allí hasta que reconstruya el proyecto.

Todo esto se ejecuta en .NET 4.0 en mi máquina local.

+0

¿Tiene alguna configuración de configuración de caché extraña en su web.config? –

+0

No, tengo predeterminado web.config – smoak

Respuesta

12

Resulta que esta línea:

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

elimina el valor anterior y re-inserta el valor sin tiempo de caducidad absoluta o deslizamiento. Con el fin de evitar esto tuve que crear una clase de ayuda y lo utilizan de esta manera:

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

Esto hará que todo el asunto y dejar que expire el contador adecuadamente en el tiempo absoluto al tiempo que permite cambios a la misma.

+0

Esta es una situación en la que la API es demasiado útil. En lugar de forzarlo a trabajar con el mecanismo de almacenamiento usando el indexador como vio, conduce a la extrañeza –

+1

Estoy de acuerdo. Eventualmente, solo revisé la fuente usando [ilspy] (http://wiki.sharpdevelop.net/ilspy.ashx) para descubrir todo esto. – smoak

3

Intente utilizar DateTime.UtcNow para calcular su período de tiempo de espera en lugar de fecha y hora. Ahora. Puede que esté ejecutando en el tema se describe a continuación:

Tipo absoluteExpiration: System.DateTime El momento en que el objeto insertado caduca y se elimina de la caché. Para evitar posibles problemas con la hora local como los cambios del horario estándar al horario de verano , utilice UtcNow en lugar de Now para este valor del parámetro. Si está utilizando la expiración absoluta , el parámetro slidingExpiration debe ser NoSlidingExpiration.

+0

Cambiándolo para usar DateTime.UtcNow.AddMinutes (5); no funcionó :( – smoak

+0

Bummer Creo que su código es correcto. Me parece correcto. ¿Cuándo se elimina de la memoria caché? Puede agregar una devolución de llamada a la memoria caché.insert para averiguar cuándo se elimina.Tal vez eso te dará una pista sobre qué lo está desencadenando. –

+0

Eso es lo que sucede, no se elimina del caché. Ese es el problema que estoy experimentando. Espero que se elimine después de 5 minutos, sin embargo, permanece allí hasta que reconstruya el proyecto. – smoak

0

Hay una respuesta más simple que la que publicó smoak. Usando ese ejemplo como punto de partida, el código actualizado a continuación funciona y no requiere una nueva inserción. La razón por la que esto funciona es porque las clases son tipos de referencia. Por lo tanto, cuando actualiza el contador dentro de la instancia de clase, no causa que la memoria caché active una actualización.

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++; 
    } 
} 
Cuestiones relacionadas