结合滑动和绝对到期
本文关键字:结合 | 更新日期: 2023-09-27 18:13:22
我想使用System.Runtime.Caching.MemoryCache
缓存我的一些对象。我想确保对象每天刷新一次(绝对过期),但我也想让它过期,如果它在最后一个小时内没有使用(滑动过期)。我试着做:
object item = "someitem";
var cache = MemoryCache.Default;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now.AddDays(1);
policy.SlidingExpiration = TimeSpan.FromHours(1);
cache.Add("somekey", item, policy);
但是我得到一个错误:
"ArgumentException"必须带有"AbsoluteExpirationDateTimeOffset。MaxValue或SlidingExpiration必须为TimeSpan.Zero."
可以通过使用CacheEntryChangeMonitor来实现这两种方案的缓存过期。插入一个没有绝对过期信息的缓存项,然后用这个项创建一个空的monitorChange,并将它与第二个缓存项链接,在这个缓存项中,您将实际保存一个slidingTimeOut信息。
object data = new object();
string key = "UniqueIDOfDataObject";
//Insert empty cache item with absolute timeout
string[] absKey = { "Absolute" + key };
MemoryCache.Default.Add("Absolute" + key, new object(), DateTimeOffset.Now.AddMinutes(10));
//Create a CacheEntryChangeMonitor link to absolute timeout cache item
CacheEntryChangeMonitor monitor = MemoryCache.Default.CreateCacheEntryChangeMonitor(absKey);
//Insert data cache item with sliding timeout using changeMonitors
CacheItemPolicy itemPolicy = new CacheItemPolicy();
itemPolicy.ChangeMonitors.Add(monitor);
itemPolicy.SlidingExpiration = new TimeSpan(0, 60, 0);
MemoryCache.Default.Add(key, data, itemPolicy, null);
在调用MemoryCache.Add
if (policy.AbsoluteExpiration != ObjectCache.InfiniteAbsoluteExpiration && policy.SlidingExpiration != ObjectCache.NoSlidingExpiration)
{
throw new ArgumentException(R.Invalid_expiration_combination, "policy");
}
因此,本机不支持绝对过期和滑动过期的组合。
您应该转向自定义实现
您有两个选择:
- 继承
MemoryCache
或它的父ObjectCache
,并实现自己的缓存机制。 - 实现
ChangeMonitor
,这可能会更困难(见继承者注意事项)
对dieguitoffernandez的回答(顺便说一句,这是一个非常好的解决方案)的一点额外说明:
ChangeMonitor没有在达到AbsoluteExpiration的确切时刻发出警报,因为没有每秒钟检查一次Expiration。可能需要几秒钟的时间才能通知第二个缓存项。用1天作为AbsoluteExpiration没关系,但是如果你需要两个到期时间都是精确的(就像我一样),你必须首先使用两个键和绝对键。
if (cache.Contains("Absolute" + key) && cache.Contains(key))
这样可以立即检查两个过期时间,您可以确定项目没有过期。
(我可以把这个作为评论,因为我是新来的,抱歉!)
DateTime.Now.AddDays(1)
不返回DateTimeOffset,而是DateTime (AddDays())。
所以它很可能是一个无效参数
所以,试试DateTimeOffset.Now.AddDays(1)
(DateTimeOffset)。