MemoryCache UpdateCallback не работает - PullRequest
5 голосов
/ 11 марта 2012

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

Оказалось, что 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

Что я делаю не так?

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

Ответы [ 3 ]

4 голосов
/ 11 марта 2012

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

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

Вместо сна.

1 голос
/ 27 декабря 2012

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

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

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

Кстати, RemovedCallback не меняет поведение.

0 голосов
/ 25 февраля 2014

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

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

...