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. Я не думаю, что это необходимо в вашем случае, кроме того, когда вы это называете.