Объединить раздвижные и абсолютные сроки
Я хочу использовать 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."
Ответы
Ответ 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 не поддерживается изначально.
Вы должны переключиться на пользовательскую реализацию.
Ответ 3
У вас есть два варианта:
Ответ 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).