.NET 4 ObjectCache - 我们可以陷入“缓存过期”事件吗?

时间:2011-10-05 04:20:54

标签: c# caching .net-4.0 objectcache

我有一个像这样缓存的简单对象:

_myCache.Add(someKey, someObj, policy);

_myCache被声明为ObjectCache(但通过DI注入为MemoryCache.Default),someObj是我要添加的对象,而policyCacheItemPolicy

如果我有CacheItemPolicy这样的话:

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

这意味着它将在1小时后到期。凉。

但会发生的事情是,一小时后不幸的第一个用户将不得不等待命中。

有什么方法可以挂钩到“过期”的事件/委托并手动刷新缓存?

我看到提到CacheEntryChangeMonitor,但在我的示例中找不到任何有意义的doco /示例如何使用它。

PS。我知道我可以使用CacheItemPriority.NotRemovable并手动过期,但我不能在我当前的例子中这样做,因为缓存的数据有点太复杂(例如我需要在10个不同的地方“无效”我的代码)。

有什么想法吗?

3 个答案:

答案 0 :(得分:14)

CacheItemPolicy上有一个名为RemovedCallback的属性,其类型为:CacheEntryRemovedCallback。不确定为什么他们没有采用标准的活动路线,但这应该做你需要的。

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

答案 1 :(得分:5)

参加派对的人来晚了,但我刚刚注意到CacheItemUpdate和CacheItemRemove回调之间存在一些有趣的区别。

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

特别是这条评论:

  

与CacheItemRemovedReason枚举不同,此枚举可以   不包括已删除或未使用的值。可更新的缓存项目   是不可移动的,因此永远不会被自动删除   ASP.NET即使有需要释放内存。

答案 2 :(得分:1)

这是我在缓存过期时使用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's needed
                    Task.Run(() =>
                    {
                    });
                }

            }