MemoryCache Empty: возвращает null после установки
У меня проблема с приложением 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"]);
Когда он работает, предсказуемо "fred" печатается. Однако, когда проблема начинает возникать, несмотря на Set()
, значение MemoryCache.Default["myname"]
равно null. Я могу это доказать, установив точку останова на строке Response.Write()
и непосредственно установив и прочитав из кеша, используя окно Immediate - оно просто не установит его и останется нулевым! Единственный способ заставить его снова работать, - это вызвать утилиту AppDomain.
Интригующе я могу спровоцировать возникшую проблему, когда приложение работает нормально, разбившись на строку Response.Write()
и запустив MemoryCache.Default.Dispose()
. После этого MemoryCache.Default не является нулевым (почему это?), Но не сохранит ничего, установленного на нем. Это не вызывает никаких ошибок, но ничего не спасет.
Кто-нибудь может это подтвердить и объяснить? Как я полагаю, я обнаружил, что когда приложение перестает работать самостоятельно, что-то есть Disposing MemoryCache.Default
, но это не я!
UPDATE
Ну, мне сейчас надоело эта проблема! CLRProfiler, похоже, не работает с MVC 3. Инструмент SciTech CLR был хорош - так был RedGate ANTS. Но все, что они сказали мне, это то, что объект MemoryCache устраивает что-то! Я также доказал (через печать временной метки), что PartialView на моей странице, который должен быть кэширован (указанный OutputCacheAttribute), перестает быть кешированным через несколько минут - он начинает обновляться при каждом вызове страницы. Чтобы уточнить среду, я запускаю непосредственно на сервере IIS 7.5 на моей рабочей станции разработки под управлением Win 7 Ultimate. Упомянутые выше средства памяти предполагают, что я использую только около 9 МБ памяти с точки зрения объектов в игре.
В отчаянии я изменил свой код кеширования, чтобы сначала найти окружающий HttpContext, чтобы подключиться к нему и использовать его функции кэширования, если он доступен. Ранние тесты показывают, что это надежно, но это похоже на неприятный взлом.
У меня возникает ощущение, что MemoryCache и OutputCache не гарантируют работу с MVC 3...
Ответы
Ответ 1
Итак, вот некоторые новости. Мы рассмотрели это и ДА, это ошибка в .NET 4.
Хорошей новостью является то, что она была исправлена в .NET 4.5, поэтому, если вы можете, обновите свою установку до .NET 4.5, и вы будете тверды.
Другая хорошая новость, что это исправление было перенесено на .NET 4 и будет доступно в виде QFE (Quick Fix... одно исправление, которое вы примените) # 578315. Он был backported/fixed только несколько дней назад, и он должен быть как можно скорее. Я постараюсь получить точную дату, но скоро.
Другая хорошая новость заключается в том, что для .NET 4 перед QFE существует обходной путь. Обходной путь является странным, но он может разблокировать вас.
using (ExecutionContext.SuppressFlow()) {
// Create memory cache instance under disabled execution context flow
return new YourCacheThing.GeneralMemoryCache(…);
}
Надеюсь, что это поможет.
UPDATE: исправление http://support.microsoft.com/kb/2828843, и вы можете запросить его здесь: https://support.microsoft.com/contactus/emailcontact.aspx?scid=sw;%5BLN%5D;1422
Ответ 2
У нас та же проблема. Я подтверждаю, что после некоторого периода времени кеш стал удаляться. Это частное поле _disposed стало 1. Я уверен, что у меня нет вызова в cache.Dispose в моем коде. Но когда я посмотрел на код 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 он вызывает разгрузку домена, но сохраняет кеш в памяти (я не уверен, если это возможно).
Ответ 3
У меня были такие же симптомы. Наконец, я привел к использованию класса System.Web.Cache и подключению к HttpContext.Cache. Он работает отлично в течение последних 3 дней.
Ответ 4
См. также эти ссылки, связанные с одной и той же проблемой.
MemoryCache устанавливается после PollingInterval при использовании в WebApp в режиме Integrated Pipeline
http://connect.microsoft.com/VisualStudio/feedback/details/764911/memorycache-gets-disposed-after-pollinginterval-when-used-in-webapp-in-integrated-pipeline-mode
MemoryCache входит в состояние Disposed Magical
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/1233ffb3-6480-431b-94ca-1190f96cf5f6
Ответ 5
MemoryCache
автоматически вытеснит элементы, если он достигнет предела памяти. Это может произойти в вашем случае, есть ли у вас много элементов в кеше?
Вы можете контролировать пределы с помощью configuration. По умолчанию он оптимизируется на основе доступной памяти.
Конечно, вызов Dispose
остановит экземпляр MemoryCache
, который будет очищать все неуправляемые ресурсы, готовые к удалению. Вы должны называть только Dispose
, если вы больше не собираетесь использовать MemoryCache
. Я не думаю, что это необходимо в вашем случае, кроме того, когда вы это называете.