我在Microsoft.Extensions.Caching.Memory.MemoryCache中设置了具有滑动过期的缓存项。 我想在每次缓存项到期时触发回调,但是在我查询缓存中过期的缓存项之前,不会触发回调。
以下是代码:
destroy
答案 0 :(得分:7)
要添加接受答案和评论,您可以使用过期的取消令牌强制缓存过期并自动逐出。
int expirationMinutes = 60;
var expirationTime = DateTime.Now.Add(expirationMinutes);
var expirationToken = new CancellationChangeToken(
new CancellationTokenSource(TimeSpan.FromMinutes(expirationMinutes + .01)).Token);
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Pin to cache.
.SetPriority(CacheItemPriority.NeverRemove)
// Set the actual expiration time
.SetAbsoluteExpiration(expirationTime)
// Force eviction to run
.AddExpirationToken(expirationToken)
// Add eviction callback
.RegisterPostEvictionCallback(callback: CacheItemRemoved, state: this);
`
缺乏内置的计时器行为,旧的曾经有过,应该是设计的,这就是它所建议的。请参阅:https://github.com/aspnet/Caching/issues/248
答案 1 :(得分:3)
这种情况正在发生,因为在您查询该项目并检查到期时,该项目不会被逐出
(来自MemoryCacheStore.Get(MemoryCacheKey key)
的来源)
internal MemoryCacheEntry Get(MemoryCacheKey key) {
MemoryCacheEntry entry = _entries[key] as MemoryCacheEntry;
// has it expired?
if (entry != null && entry.UtcAbsExp <= DateTime.UtcNow) {
Remove(key, entry, CacheEntryRemovedReason.Expired);
entry = null;
}
// update outside of lock
UpdateExpAndUsage(entry);
return entry;
}
或由于记忆压力而在内部调用Trim()
(来自TrimInternal(int percent)
的来源)
/*SNIP*/
trimmedOrExpired = _expires.FlushExpiredItems(true);
if (trimmedOrExpired < toTrim) {
trimmed = _usage.FlushUnderUsedItems(toTrim - trimmedOrExpired);
trimmedOrExpired += trimmed;
}
/*SNIP*/
如果您的系统目前内存不足以触发修剪,那么唯一可以驱逐项目的时间是尝试检索它们。