.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 разных мест в моем коде).
Любые идеи?
Ответы
Ответ 1
Здесь свойство CacheItemPolicy
называется RemovedCallback
, которое имеет тип: CacheEntryRemovedCallback
. Не знаете, почему они не пошли по стандартным маршрутам событий, но это должно делать то, что вам нужно.
http://msdn.microsoft.com/en-us/library/system.runtime.caching.cacheitempolicy.removedcallback.aspx
Ответ 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(() =>
{
});
}
}