.NET 4 ObjectCache - можем ли мы подключиться к событию "Кэш истек"?

У меня есть простой объект, который кэшируется следующим образом:

_myCache.Add(someKey, someObj, policy);

Где _myCache объявляется как ObjectCache (но вводится через DI как MemoryCache.Default), someObj - это объект, который я добавляю, а policy - CacheItemPolicy.

Если у меня есть CacheItemPolicy, как это:

var policy = new CacheItemPolicy 
{ 
   Priority = CacheItemPriority.Default, 
   SlidingExpiration = TimeSpan.FromHours(1)
};

Это означает, что он истечет через 1 час. Круто.

Но произойдет то, что неудачный первый пользователь после часа должен будет дождаться удара.

Можно ли каким-либо образом подключить событие/делегат с истекшим сроком действия и вручную обновить кеш?

Я вижу, что есть упоминание CacheEntryChangeMonitor, но не может найти каких-либо средних версий doco/примеров того, как использовать его в моем примере.

PS. Я знаю, что могу использовать CacheItemPriority.NotRemovable и истекать его вручную, но я не могу этого сделать в моем текущем примере, потому что кэшированные данные немного сложны (например, мне нужно будет "аннулировать" как 10 разных мест в моем коде).

Любые идеи?

Ответ 2

Позднее с этим, но я только что заметил интересную разницу между обратными вызовами CacheItemUpdate и CacheItemRemove.

http://msdn.microsoft.com/en-us/library/system.web.caching.cacheitemupdatereason.aspx

В частности, этот комментарий:

В отличие от перечисления CacheItemRemovedReason, это перечисление делает не включает значения "Удалено" или "Недоиспользовано". Обновляемые элементы кэша не являются съемными и поэтому не могут быть автоматически удалены ASP.NET, даже если есть необходимость освободить память.

Ответ 3

Это мой способ использовать событие CacheRemovedCallback, когда срок действия кэша истек.

Я разделяю для кого беспокойство.

public static void SetObjectToCache<T>(string cacheItemName, T obj, long expireTime)
        {
            ObjectCache cache = MemoryCache.Default;

            var cachedObject = (T)cache[cacheItemName];

            if (cachedObject != null)
            {
                // remove it
                cache.Remove(cacheItemName);
            }

            CacheItemPolicy policy = new CacheItemPolicy()
            {
                AbsoluteExpiration = DateTimeOffset.Now.AddMilliseconds(expireTime),
                RemovedCallback = new CacheEntryRemovedCallback(CacheRemovedCallback)
            };

            cachedObject = obj;
            cache.Set(cacheItemName, cachedObject, policy);
        }

public static void CacheRemovedCallback(CacheEntryRemovedArguments arguments)
            {
                var configServerIpAddress = Thread.CurrentPrincipal.ConfigurationServerIpAddress();
                long configId = Thread.CurrentPrincipal.ConfigurationId();
                int userId = Thread.CurrentPrincipal.UserId();
                var tagInfoService = new TagInfoService();
                string returnCode = string.Empty;

                if (arguments.CacheItem.Key.Contains("DatatableTags_"))
                {
                    // do what needed
                    Task.Run(() =>
                    {
                    });
                }

            }