MemoryCache Empty: возвращает ноль после установки
У меня проблема с приложением MVC 3, использующим новую.NET 4 System.Runtime.Caching MemoryCache. Я замечаю, что после, казалось бы, непредсказуемого времени, он перестает кэшировать вещи и действует как пустой. Рассмотрим этот фрагмент кода, который я взял прямо из тестового представления в ASP.NET MVC:
MemoryCache.Default.Set("myname","fred", new CacheItemPolicy() { SlidingExpiration = new TimeSpan(0,5,0) });
Response.Write(MemoryCache.Default["myname"]);
Когда это работает, предсказуемо печатается "Фред". Однако, когда проблема начинает возникать, несмотря на Set()
, значение MemoryCache.Default["myname"]
нулевой. Я могу доказать это, установив точку останова на Response.Write()
прямая установка и чтение из кеша с помощью окна Immediate - он просто не будет установлен и останется нулевым! Тогда единственный способ заставить его работать снова - это перезапустить AppDomain.
Интересно, что я могу спровоцировать возникновение проблемы, когда приложение работает нормально, взломав Response.Write()
линия и бег MemoryCache.Default.Dispose()
, После этого MemoryCache.Default сам по себе не равен нулю (почему это так?), Но не будет сохранять на нем ничего установленного. Это не вызывает никаких ошибок, но ничего не спасет.
Кто-нибудь может это проверить и объяснить? Как я полагаю, я обнаружил, что когда приложение перестает работать само по себе, что-то MemoryCache.Default
, но это не я!
ОБНОВИТЬ
Ну, мне надоел этот пробник сейчас! CLRProfiler, похоже, не работает с MVC 3. Инструмент SciTech CLR был хорош - как и RedGate ANTS. Но все, что мне сказали, это то, что объект MemoryCache чем-то уничтожен! Я также доказал (с помощью печати временной метки), что PartialView на моей странице, который должен быть кэширован (задан OutputCacheAttribute), перестает кэшироваться через несколько минут - он начинает обновляться при каждом обращении к странице. Просто чтобы прояснить среду, я работаю прямо на сервере IIS 7.5 на моей рабочей станции, на которой работает Win 7 Ultimate. Упомянутые выше инструменты памяти предполагают, что я использую только около 9 МБ памяти в терминах объектов в игре.
В отчаянии я изменил свой код кэширования, чтобы сначала найти окружающий HttpContext, чтобы подключить и использовать его функции кэширования, если таковые имеются. Ранние тесты показывают, что это надежно, но похоже на неприятный взлом.
У меня возникает ощущение, что MemoryCache и OutputCache не гарантированы для работы с MVC 3...
5 ответов
Итак, вот некоторые новости. Мы рассмотрели это и ДА, это ошибка в.NET 4.
Хорошая новость заключается в том, что она была исправлена в.NET 4.5, поэтому, если вы можете, обновите установку до.NET 4.5, и все готово.
Другая хорошая новость заключается в том, что это исправление перенесено в.NET 4 и будет доступно в виде QFE (Быстрое исправление... одноразовое исправление, которое вы примените) #578315. Это было перенесено / исправлено всего несколько дней назад, и оно должно быть как можно скорее. Я постараюсь получить точную дату, но это скоро.
Другая хорошая новость заключается в том, что есть обходной путь в.NET 4 до QFE. Обходной путь странный, но он может разблокировать вас.
using (ExecutionContext.SuppressFlow()) {
// Create memory cache instance under disabled execution context flow
return new YourCacheThing.GeneralMemoryCache(…);
}
Надеюсь это поможет.
ОБНОВЛЕНИЕ: исправление http://support.microsoft.com/kb/2828843 и вы можете запросить его здесь: https://support.microsoft.com/contactus/emailcontact.aspx?scid=sw;%5BLN%5D;1422
У нас та же проблема. Я подтверждаю, что через некоторое время кеш стал ликвидным. Это личное поле _disposed стал 1. Я уверен, что у меня нет вызова кеша. Уничтожить в моем коде. Но когда я посмотрел код MemoryCache с Reflector, то увидел, что в конструкторе он подписывается на два события
domain.DomainUnload += eventHandler;
domain.UnhandledException += exceptionEventHandler;
private void OnAppDomainUnload(object unusedObject, EventArgs unusedEventArgs)
{
this.Dispose();
}
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs eventArgs)
{
if (!eventArgs.IsTerminating)
return;
this.Dispose();
}
Оба из этих обработчиков событий имеют вызов Dispose. Может быть, после некоторой перезапуска домена в IIS это вызывает выгрузку домена, но сохраняет кэш в памяти (я не уверен, если это возможно).
Я испытывал точно такие же симптомы. Я наконец-то привел к использованию класса System.Web.Cache и подключению к HttpContext.Cache. Работает отлично последние 3 дня.
Смотрите также эти ссылки, связанные с той же проблемой.
MemoryCache удаляется после PollingInterval при использовании в WebApp в режиме Integrated Pipeline.
MemoryCache магически переходит в состояние Disposed
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/1233ffb3-6480-431b-94ca-1190f96cf5f6
MemoryCache
автоматически изгонит предметы, если достигнет предела памяти. Это может произойти в вашем случае, у вас есть много элементов в кэше?
Вы можете контролировать пределы с помощью конфигурации. По умолчанию он оптимизируется на основе доступной памяти.
Конечно звонит Dispose
остановит MemoryCache
Экземпляр работает, поскольку он очистит все неуправляемые ресурсы, готовые к утилизации. Вы должны только позвонить Dispose
если вы не собираетесь использовать MemoryCache
больше Я не думаю, что это является необходимой проблемой в вашем случае, за исключением случаев, когда вы это называете.