我正在尝试以编程方式刷新IMemoryCache
。研究了几个链接之后
关于Eviction Calback和Clearing cache,我认为我可以结合使用这些策略,即清除将导致驱逐回调触发的缓存。但是,显然,使用反射清除缓存后,将不会触发驱逐后回调,因为似乎所有带有其选项的缓存项(包括callback)都已消失。 (缓存项计数为0)
所以我的问题是,由于this issue仍处于打开状态,因此在过期之前刷新缓存项
private static Dictionary<string, CancellationTokenSource> tokenDict = new Dictionary<string, CancellationTokenSource>();
private MemoryCacheEntryOptions CacheOptions
{
get
{
var expirationToken = new CancellationChangeToken( new CancellationTokenSource(TimeSpan.FromMinutes(ExpirationMinutes + .01)).Token);
var options = new MemoryCacheEntryOptions()
// Do not remove due to memory pressure
.SetPriority(Microsoft.Extensions.Caching.Memory.CacheItemPriority.NeverRemove)
.SetSlidingExpiration(TimeSpan.FromMinutes(ExpirationMinutes))
// Force eviction to run AT expriry, default eviction happens when item is requested after expiry
.AddExpirationToken(expirationToken)
.RegisterPostEvictionCallback(callback: CacheItemRemoved, state: this);
tokenDict[cacheKey] = cancellationTokenSource;
return options;
}
}
private void CacheItemRemoved(object key, object value, EvictionReason reason, object state)
{
_logger.LogInformation($"Reloading {key} cache upon eviction");
switch (key)
{
case AccountCacheKey:
GetAccountCacheAsync();
break;
case FundCacheKey:
GetFundCacheAsync();
break;
default:
break;
}
}
private async Task<List<Account>> GetAccountCacheAsync()
{
return await _cache.GetOrCreateAsync(AccountCacheKey, async entry =>
{
entry.SetOptions(CacheOptions);
var accounts = await LoadAccountsAsync().ConfigureAwait(false);
return accounts;
}).ConfigureAwait(false);
}
private async Task<List<Fund>> GetFundCacheAsync()
{
return await _cache.GetOrCreateAsync(FundCacheKey, async entry =>
{
entry.SetOptions(CacheOptions);
var funds = await LoadFundsAsync().ConfigureAwait(false);
return funds;
}).ConfigureAwait(false);
}
public async Task RefreshCacheAsync()
{
var cacheKeys = new List<string> { AccountCacheKey, FundCacheKey };
foreach (var key in cacheKeys)
{
if (tokenDict.TryGetValue(key, out var token))
{
if (token != null && !token.IsCancellationRequested && token.Token.CanBeCanceled)
{
token.Cancel();
token.Dispose();
}
}
}
}
答案 0 :(得分:2)
您已经发布了具有最佳方法的链接,但是您似乎选择了评分较低的答案之一,但这实际上无法满足您的目的。相反,您应该遵循此answer。它创建了一个缓存“管理器”类,该类除其他外还使用CancellationTokenSource
来处理驱逐。这实际上与您链接的Github问题中推荐的方法相同。