2012-03-10 10 views
5

Intento crear un conjunto de conexiones a una API de terceros y las conexiones caducan después de un intervalo si no están en uso. Cuando caducan, deben desconectarse a través de la API de terceros.MemoryCache UpdateCallback no funciona

Parece que MemoryCache (System.Runtime.Caching) se encargará de esto. UpdateCallback parece comportarse de manera extraña, sin embargo.

Un ejemplo sencillo LINQPad:

void Main() 
{ 
    var cache = MemoryCache.Default; 
    var policy = new CacheItemPolicy(); 
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(1); 
    policy.UpdateCallback = Update; 
    cache.Set("figkey", "fig", policy); 

    Thread.Sleep(2000); 

    object result = cache.Get("figkey"); 

    Console.WriteLine(result == null ? "null" : result); 
} 

public static void Update(CacheEntryUpdateArguments arguments) 
{ 
    Console.WriteLine("got here"); 
} 

Si funciono esto, la salida es:

fig 

lo hace NO salida "tiene aquí".

Si comento hacia fuera la línea que comienza con policy.UpdateCallback, la salida es:

null 

¿Qué estoy haciendo mal?

Si hay una mejor manera de llevar a cabo mi tarea, estoy abierto a sugerencias alternativas.

Respuesta

4

Creo que el problema puede ser el Thread.Sleep porque eso también bloquea la memoria caché, ya que se ejecutan en el mismo hilo. Si intenta hacer bucles ficticios, verá que el controlador de actualización se activó:

var i = 0; 
for (var j = 0; j < 10000000; j++) 
{ 
    for (var k = 0; k < 1000000; k++) 
     i++; 
    i--; 
} 
Console.WriteLine(i); 

En lugar de la suspensión.

+0

Su ejemplo funciona. Puedo obtener "get here" seguido de "null" (que es lo que esperaría). Esto parece extraño: pensé que la caducidad del caché ocurriría en otro hilo. ¡Gracias! – TrueWill

1

Simplemente agregue Console.ReadLine() al final de Main o reemplace Sleep con Console.ReadLine(), inicie su muestra y espere unos 10 segundos. Obtendrás el mensaje esperado. El temporizador dentro de MemoryCache es un poco lento.

Pero de todos modos, ciertamente hay un error en MemoryCache: la asignación de UpdateCallback cambia el comportamiento, pero no debería.

En caso de que se establezca AbsoluteExpiration y se pase el tiempo, el método Get debe devolver null sin una dependencia en la existencia de UpdateCallback.

BTW, RemovedCallback no cambia el comportamiento.

0

Simplemente aumente el tiempo de suspensión a algo mucho más grande y verá que se ejecuta la devolución de llamada.

La caducidad se produce en otro subproceso a través de un temporizador (puede ver tanto si establece un punto de interrupción dentro de la devolución de llamada). Esta es la razón por la cual dormir o esperar ocupado funciona.