Принудительное обновление IMemoryCache - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь обновить IMemoryCache программно.Изучив несколько ссылок о Eviction Calback и Очистка кэша , я подумал, что мог бы объединить стратегии, то есть очистить кэш, что вызовет обратный вызов изгнания.Однако очевидно, что обратный вызов после выселения не сработает, когда кэш очищается с помощью отражения, поскольку кажется, что весь элемент кэша с его параметрами (включая обратный вызов) пропал.(количество элементов кэша равно 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();
                }
            }
        }
    }

1 Ответ

2 голосов
/ 17 апреля 2019

Вы уже разместили ссылку с лучшим подходом, но, похоже, вы выбрали один из ответов с более низким рейтингом, который на самом деле не работает для ваших целей.Вместо этого вы должны следовать этому ответу .Он создает кеш-класс «менеджер», который, помимо прочего, использует CancellationTokenSource для обработки выселения.На самом деле это тот же метод, который был рекомендован в проблеме Github, которую вы связали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...