2012-03-10 6 views
5

Я пытаюсь создать пул подключений к стороннему API и истекает срок действия соединений через интервал, если они не используются. Когда они истекают, они должны быть отключены через сторонний API.MemoryCache UpdateCallback не работает

Оказалось, что MemoryCache (System.Runtime.Caching) справится с этим. Однако UpdateCallback ведет себя странно.

Простой пример 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"); 
} 

Если я запускаю это, выход:

fig 

Это НЕ выход "попал сюда".

Если я закомментируйте строку, начинающуюся с policy.UpdateCallback, выход:

null 

Что я делаю неправильно?

Если есть лучший способ выполнить мою задачу, я открыт для альтернативных предложений.

ответ

4

Я думаю, что проблема может быть Thread.Sleep, потому что это также блокирует кеш, поскольку они работают в одном потоке. Если вы пытаетесь сделать фиктивные петли вы себе, что обработчик обновления запускается:

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

Вместо сна.

+0

Ваш пример работает. Я могу получить «сюда», за которым следует «null» (что я и ожидал). Это кажется странным - я думал, что истечение срока действия кеша произойдет в другом потоке. Благодаря! – TrueWill

1

Просто добавьте Console.ReadLine() в конец Main или замените Sleep with Console.ReadLine(), запустите свой образец и подождите около 10 секунд. Вы получите ожидаемое сообщение. Таймер внутри MemoryCache немного медленный.

Но, в любом случае, в MemoryCache определенная ошибка: назначение UpdateCallback изменяет поведение, но это не должно.

В случае установки AbsoluteExpiration и передачи времени метод Get должен возвращать null без зависимости от наличия UpdateCallback.

BTW, RemovedCallback не изменяет поведение.

0

Просто увеличьте время сна до чего-то большего, и вы увидите, что обратный вызов выполняется.

Истечение срока действия происходит в другом потоке через таймер (вы можете видеть столько, если вы установите точку останова в обратном вызове). Вот почему работает сон или ожидание.

Смежные вопросы