Asp.net core 强制刷新IMemoryCache

Asp.net core 强制刷新IMemoryCache,asp.net-core,Asp.net Core,我正在尝试以编程方式刷新IMemoryCache。在研究了几个链接之后 关于和,我认为我可以结合使用这些策略,即清除缓存,这将导致驱逐回调触发。然而,显然,当使用反射清除缓存时,驱逐后回调不会触发,因为似乎整个缓存项及其选项(包括回调)都消失了。(缓存项计数变为0) 所以我的问题是关于在到期之前刷新缓存项,因为它仍然是打开的 private static Dictionary<string, CancellationTokenSource> tokenDict = new D

我正在尝试以编程方式刷新
IMemoryCache
。在研究了几个链接之后 关于和,我认为我可以结合使用这些策略,即清除缓存,这将导致驱逐回调触发。然而,显然,当使用反射清除缓存时,驱逐后回调不会触发,因为似乎整个缓存项及其选项(包括回调)都消失了。(缓存项计数变为0)

所以我的问题是关于在到期之前刷新缓存项,因为它仍然是打开的

    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();
                }
            }
        }
    }
private static Dictionary tokenDict=new Dictionary();
私有内存缓存选项缓存选项
{
得到
{
var expirationToken=新的CancellationChangeToken(新的CancellationTokenSource(TimeSpan.FromMinutes(ExpirationMinutes+.01)).Token);
var options=new MemoryCacheEntryOptions()
//由于内存压力,请勿卸下
.SetPriority(Microsoft.Extensions.Caching.Memory.CacheItemPriority.NeverRemove)
.SetSlidingExpiration(TimeSpan.FromMinutes(ExpirationMinutes))
//强制逐出在expriry运行,默认逐出发生在到期后请求项时
.AddExpirationToken(expirationToken)
.RegisterPostVictionCallback(回调:CacheItemRemoved,状态:this);
tokenDict[cacheKey]=cancellationTokenSource;
返回选项;
}
}
private void CacheItemRemoved(对象键、对象值、驱逐原因、对象状态)
{
_logger.LogInformation($“退出时重新加载{key}缓存”);
开关(钥匙)
{
案例AccountCacheKey:
getAccountCacheAync();
打破
案例关键点:
GetFundCacheAsync();
打破
违约:
打破
}
}
专用异步任务GetAccountCacheAync()
{
return await\u cache.GetOrCreateAsync(AccountCacheKey,async entry=>
{
entry.SetOptions(CacheOptions);
var accounts=await LoadAccountsAsync().ConfigureAwait(false);
归还账户;
}).配置等待(错误);
}
专用异步任务GetFundCacheAync()
{
return await\u cache.GetOrCreateAsync(FundCacheKey,async entry=>
{
entry.SetOptions(CacheOptions);
var funds=await LoadFundsAsync().ConfigureAwait(false);
返还资金;
}).配置等待(错误);
}
公共异步任务刷新缓存异步()
{
var cachekey=新列表{AccountCacheKey,FundCacheKey};
foreach(cacheKeys中的var键)
{
if(tokenDict.TryGetValue(键,输出变量标记))
{
if(token!=null&&!token.IsCancellationRequested&&token.token.canbecancelled)
{
token.Cancel();
token.Dispose();
}
}
}
}

您已经发布了一个带有最佳方法的链接,但您似乎选择了一个评分较低的答案,这实际上不符合您的目的。相反,你应该遵循这一点。它创建一个缓存“管理器”类,该类使用
CancellationTokenSource
来处理逐出。这实际上与您链接的Github问题中推荐的方法相同。

您已经发布了一个具有最佳方法的链接,但您似乎选择了一个评分较低的答案,这实际上不符合您的目的。相反,你应该遵循这一点。它创建一个缓存“管理器”类,该类使用
CancellationTokenSource
来处理逐出。这实际上与您链接的Github问题中推荐的方法相同。

对不起,我的问题不够清楚-我不想转储整个缓存-我想强制刷新特定条目我通过缓存密钥设置令牌字典而不是在引用的代码中使用静态令牌来解决问题我很抱歉,我的问题还不够清楚-我不想转储整个缓存-我想强制刷新特定条目我通过使用缓存密钥设置令牌字典,而不是使用引用代码中的静态令牌更新工作代码更新工作代码,解决了这个问题