.NET 4 ObjectCache — можем ли мы подключиться к событию «Срок действия кэша истек»?

#c# #caching #.net-4.0 #objectcache

#c# #кэширование #.net-4.0 #ObjectCache

Вопрос:

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

 _myCache.Add(someKey, someObj, policy);
  

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

Если у меня есть CacheItemPolicy подобное:

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

Это означает, что срок его действия истечет через 1 час. Прохладный.

Но что произойдет, так это то, что невезучему первому пользователю через час придется ждать попадания.

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

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

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

Есть идеи?

Комментарии:

1. кстати, нет необходимости устанавливать Priority = CacheItemPriority . По умолчанию, поскольку это значение по умолчанию установлено по умолчанию 🙂

Ответ №1:

Для CacheItemPolicy вызываемого свойства есть свойство RemovedCallback типа: CacheEntryRemovedCallback . Не уверен, почему они не пошли по стандартному маршруту событий, но это должно сделать то, что вам нужно.

http://msdn.microsoft.com/en-us/library/system.runtime.caching.cacheitempolicy.removedcallback.aspx

Комментарии:

1. Ну, ссылка не содержит примера кода — на самом деле в MSDN очень мало примеров кода для кэширования во время выполнения. В конце концов я понял это, но вы могли бы сэкономить мне час, предоставив пример.

2. Пример CodeProject «Использование кэша памяти в .NET 4.0»

Ответ №2:

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

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

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

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

Комментарии:

1. Даже позже для вечеринки, но я только что заметил, что вы ссылаетесь на типы в System.Web.Caching пространстве имен, в то время как вопрос касается System.Runtime.Caching пространства имен.

2. @StevenLiekens, они перенесли кэширование в систему. Время выполнения в .NET 4, поскольку это было весьма полезно

3. Вы все еще можете использовать System.Web.Caching в .NET 4 и выше.

Ответ №3:

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

Я разделяю озабоченность по поводу кого.

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

            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's needed
                    Task.Run(() =>
                    {
                    });
                }

            }