mat*_*lto 7 .net caching memorycache asp.net-core
我在Microsoft.Extensions.Caching.Memory.MemoryCache中设置了具有滑动过期的缓存项.我想在每次缓存项到期时触发回调,但在我查询缓存中过期的缓存项之前,不会触发回调.
这是代码:
using System;
using Microsoft.Extensions.Caching.Memory;
namespace Memcache
{
public class Program
{
private static MemoryCache _cache;
private static int _cacheExpSecs;
public static void Main(string[] args)
{
_cache = new MemoryCache(new MemoryCacheOptions());
_cacheExpSecs = 2;
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(_cacheExpSecs))
.RegisterPostEvictionCallback(callback: EvictionCallback);
_cache.Set(1, "One", cacheEntryOptions);
_cache.Set(2, "Two", cacheEntryOptions);
var autoEvent = new System.Threading.AutoResetEvent(false);
System.Threading.Timer timer = new System.Threading.Timer(checkCache, autoEvent, 1000, 6000);
Console.Read();
}
private static void checkCache(Object o)
{
if(_cache.Get(1)!=null)
{
Console.WriteLine(string.Format(@"checkCache: Cache with key {0} will be removed manually and will trigger the callback.", 1));
_cache.Remove(1);
}
else
{
Console.WriteLine(string.Format("checkCache: Cache with key {0} is expired.", 1));
}
if(_cache.Get(2) != null)
{
Console.WriteLine(string.Format("checkCache: Cache with key {0} will expire in {1} seconds, but won't trigger the callback until we check it's value again.", 2, _cacheExpSecs));
}
else
{
Console.WriteLine(string.Format("checkCache: Cache with key {0} is expired.", 2));
}
}
private static void EvictionCallback(object key, object value, EvictionReason reason, object state)
{
Console.WriteLine();
Console.WriteLine("/*****************************************************/");
Console.WriteLine(string.Format("/* EvictionCallback: Cache with key {0} has expired. */", key));
Console.WriteLine("/*****************************************************/");
Console.WriteLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*yon 13
要添加到接受答案和注释,您可以使用过期的取消令牌强制缓存过期并自动逐出.
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);
Run Code Online (Sandbox Code Playgroud)
`
缺乏内置的计时器行为,旧的曾经有过,应该是设计的,这就是它所建议的.请参阅:https://github.com/aspnet/Caching/issues/248
发生这种情况是因为在您查询该项目并检查到期之前,该项目不会被驱逐
(来自 的来源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;
}
Run Code Online (Sandbox Code Playgroud)
或何时Trim()因内存压力而在内部调用
(来自 的来源TrimInternal(int percent))
/*SNIP*/
trimmedOrExpired = _expires.FlushExpiredItems(true);
if (trimmedOrExpired < toTrim) {
trimmed = _usage.FlushUnderUsedItems(toTrim - trimmedOrExpired);
trimmedOrExpired += trimmed;
}
/*SNIP*/
Run Code Online (Sandbox Code Playgroud)
如果您的系统当前的内存不够低,无法触发修剪,那么只有在尝试检索项目时才会驱逐项目。
| 归档时间: |
|
| 查看次数: |
3897 次 |
| 最近记录: |