Объединить раздвижные и абсолютные сроки - программирование
Подтвердить что ты не робот

Объединить раздвижные и абсолютные сроки

Я хочу использовать System.Runtime.Caching.MemoryCache для кэширования некоторых моих объектов. Я хочу быть уверенным, что объект обновляется один раз в день (абсолютное истечение срока действия), но я также хочу, чтобы он истекал, если он не использовался в последний час (скользящий срок действия). Я стараюсь:

object item = "someitem";
var cache = MemoryCache.Default;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now.AddDays(1);
policy.SlidingExpiration = TimeSpan.FromHours(1);
cache.Add("somekey", item, policy);

Но я получаю "ArgumentException" с "AbsoluteExpiration должен быть DateTimeOffset.MaxValue или SlidingExpiration должен быть TimeSpan.Zero."

4b9b3361

Ответ 1

Вы можете реализовать оба конца кэша схем, используя CacheEntryChangeMonitor. Вставьте элемент кэша без информации с абсолютным истечением срока действия, затем создайте пустой элемент monitorChange с этим элементом и свяжите его со вторым элементом кэша, в котором вы действительно сохраните информацию slideTimeOut.

        object data = new object();
        string key = "UniqueIDOfDataObject";
        //Insert empty cache item with absolute timeout
        string[] absKey = { "Absolute" + key };
        MemoryCache.Default.Add("Absolute" + key, new object(), DateTimeOffset.Now.AddMinutes(10));

        //Create a CacheEntryChangeMonitor link to absolute timeout cache item
        CacheEntryChangeMonitor monitor = MemoryCache.Default.CreateCacheEntryChangeMonitor(absKey);

        //Insert data cache item with sliding timeout using changeMonitors
        CacheItemPolicy itemPolicy = new CacheItemPolicy();
        itemPolicy.ChangeMonitors.Add(monitor);
        itemPolicy.SlidingExpiration = new TimeSpan(0, 60, 0);
        MemoryCache.Default.Add(key, data, itemPolicy, null);

Ответ 2

Быстрое отражение с помощью ILSpy показывает этот код при вызове MemoryCache.Add

if (policy.AbsoluteExpiration != ObjectCache.InfiniteAbsoluteExpiration && policy.SlidingExpiration != ObjectCache.NoSlidingExpiration)
    {
        throw new ArgumentException(R.Invalid_expiration_combination, "policy");
    }

Итак, эта комбинация Absolute и Sliding Expiration не поддерживается изначально.

Вы должны переключиться на пользовательскую реализацию.

Ответ 4

Несколько дополнительных примечаний к ответу dieguitofernandez (что, кстати, очень хорошее решение):

ChangeMonitor не разгоняется в тот момент, когда достигается AbsoluteExpiration, потому что Expiration не проверяется каждую секунду. Это может занять несколько секунд, пока не будет уведомлен второй кешированный элемент. В течение 1 дня как AbsoluteExpiration это не имеет значения, но если вам нужно, чтобы и то и другое было точным (как и я), вы должны сначала использовать оба ключа и абсолютный ключ.

if (cache.Contains("Absolute" + key) && cache.Contains(key))

Таким образом, оба истечения сразу проверяются, и вы можете быть уверены, что элемент не истек.

(я могу опубликовать это как комментарий, потому что я здесь новый, извините!)

Ответ 5

DateTime.Now.AddDays(1) не возвращает DateTimeOffset, а DateTime (AddDays()).

Поэтому это скорее всего неверный аргумент.

Итак, попробуйте DateTimeOffset.Now.AddDays(1) (DateTimeOffset).