强制刷新IMemoryCache

时间:2019-04-17 15:29:51

标签: asp.net-core

我正在尝试以编程方式刷新IMemoryCache。研究了几个链接之后 关于Eviction CalbackClearing 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();
                }
            }
        }
    }

1 个答案:

答案 0 :(得分:2)

您已经发布了具有最佳方法的链接,但是您似乎选择了评分较低的答案之一,但这实际上无法满足您的目的。相反,您应该遵循此answer。它创建了一个缓存“管理器”类,该类除其他外还使用CancellationTokenSource来处理驱逐。这实际上与您链接的Github问题中推荐的方法相同。