Подтвердить что ты не робот

Изменение частоты истечения срока действия кэша ASP.NET?

Я заметил, что элементы кэша ASP.NET проверяются (и, возможно, удаляются) каждые 20 секунд (и, как ни странно, каждый раз в HH: MM: 00, HH: MM: 20 и HH: MM: 40). Я потратил около 15 минут на то, как изменить этот параметр без каких-либо успехов. Я также попытался установить следующее в web.config, но это не помогло:

<cache privateBytesPollTime="00:00:05" />

Я не пытаюсь сделать что-то безумное, но было бы неплохо, если бы это было, скажем, 5 секунд вместо 20 или по меньшей мере 10 для моего приложения.

4b9b3361

Ответ 1

Выкалывание с помощью Reflector показывает, что интервал жестко запрограммирован. Expiry обрабатывается внутренним классом CacheExpires, статический конструктор которого содержит

_tsPerBucket = new TimeSpan(0, 0, 20);

_tsPerBucket - readonly, поэтому не может быть никаких параметров конфигурации, которые впоследствии изменят его.

Затем таймер, запускающий проверку устаревших элементов, устанавливается в CacheExpires.EnableExpirationTimer()...

DateTime utcNow = DateTime.UtcNow;
TimeSpan span = _tsPerBucket - new TimeSpan(utcNow.Ticks % _tsPerBucket.Ticks);
this._timer = new Timer(new TimerCallback(this.TimerCallback), null,
    span.Ticks / 0x2710L, _tsPerBucket.Ticks / 0x2710L);

Расчет span гарантирует, что таймер срабатывает точно: 00,: 20,: 40 секунд, хотя я не вижу никакой причины беспокоиться. Метод, который вызывает таймер, internal, поэтому я не думаю, что есть способ настроить ваш собственный таймер, чтобы называть его чаще (игнорируя отражение).

Однако хорошая новость заключается в том, что у вас не должно быть повода позаботиться об этом. Cache.Get() проверяет, что элемент не истек, и, если он есть, он немедленно удаляет элемент из кеша и возвращает null. Поэтому вы никогда не получите истекший элемент из кеша, хотя истекшие элементы могут оставаться в кеше на срок до 20 секунд.

Ответ 2

Согласно документации, privateBytesPollTime предназначен для использования рабочей памяти рабочего процесса, а по умолчанию - 1 секунда. Я не думаю, что это относится к удалению элемента кэша.

Я подтвердил ваши результаты с помощью обратного вызова удаления элемента - похоже, что элементы удаляются в нижней части минуты: 20 и 40 секунд. Это говорит о том, что элемент может оставаться в кеше в течение 20 секунд после установки AbsoluteExpiration. Я не мог найти документацию о том, можно ли изменить интервал опроса 20 секунд.

Ответ 3

Сумасшедшее, но рабочее решение (все шаги необходимы):

// New value for cache expiration cycle
// System.Web.Caching.CacheExpires._tsPerBucket;
// Set 1 seconds instead of 20sec
const string assembly = "System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
var type = Type.GetType("System.Web.Caching.CacheExpires, " + assembly, true, true);
var field = type.GetField("_tsPerBucket", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, TimeSpan.FromSeconds(1));

// Recreate cache
// HttpRuntime._theRuntime._cacheInternal = null;
// HttpRuntime._theRuntime._cachePublic = null;
type = typeof (HttpRuntime);
field = type.GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic);
var runtime = field.GetValue(null);
field = type.GetField("_cachePublic", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);
field = type.GetField("_cacheInternal", BindingFlags.NonPublic | BindingFlags.Instance);
field.SetValue(runtime, null);

Ответ 4

Для чего это стоит, вы можете взглянуть на вопрос который я задал: я прикрепил там пример кода, который доказывает, что, хотя я установил абсолютное время истечения 10 секунд, обратный вызов обновления происходит каждые 40 секунд.