MemoryCache Empty: Retorna null após ser definido

Eu tenho um problema com um aplicativo MVC 3 que está usando o novo .NET 4 System.Runtime.Caching MemoryCache. Percebo que, depois de um tempo aparentemente imprevisível, ele pára de armazenar em cache as coisas e age como se estivesse vazio. Considere este trecho de código que tirei direto de uma visualização de teste no ASP.NET MVC:

MemoryCache.Default.Set("myname","fred", new CacheItemPolicy() { SlidingExpiration = new TimeSpan(0,5,0) }); Response.Write(MemoryCache.Default["myname"]); 

Quando está funcionando, previsivelmente “fred” é impresso. No entanto, quando o problema começa a ocorrer, apesar do Set() , o valor de MemoryCache.Default["myname"] é nulo. Eu posso provar isso definindo um ponto de interrupção na linha Response.Write() e definindo e lendo diretamente do cache usando a Janela Imediata – Ele simplesmente não irá defini-lo e permanecerá nulo! A única maneira de fazê-lo funcionar novamente é causar uma recyclerview AppDomain.

Curiosamente, posso provocar que o problema ocorra quando o aplicativo está funcionando normalmente quebrando a linha Response.Write() e executando MemoryCache.Default.Dispose() . Depois disso, MemoryCache.Default não é nulo em si (por que isso?), Mas não salva nada definido nele. Não causa erros, mas não salva nada.

Alguém pode verificar isso e explicar? Como acredito que descobri, quando o aplicativo para de funcionar sozinho, algo está descartando MemoryCache.Default , mas não sou eu!


ATUALIZAR

Bem, estou cansado disso agora! O CLRProfiler não parece funcionar com o MVC 3. A ferramenta CLR da SciTech era boa – assim como o RedGate ANTS. Mas tudo o que eles me disseram foi que o object MemoryCache está sendo descartado por alguma coisa ! Também provei (por meio de uma impressão de timestamp) que um PartialView na minha página que deve ser armazenado em cache (especificado por OutputCacheAttribute) para de ser armazenado em cache após alguns minutos – ele começa a ser atualizado com todas as chamadas para a página. Apenas para esclarecer o ambiente, estou executando diretamente no servidor IIS 7.5 em minha estação de trabalho de desenvolvimento executando o Win 7 Ultimate. As ferramentas de memory mencionadas acima sugerem que eu estou usando apenas cerca de 9mb de memory em termos de objects em jogo.

Em desespero, mudei meu código de armazenamento em cache para primeiro procurar um HttpContext ambiente para ligar e usar sua funcionalidade de armazenamento em cache, se estiver disponível. Testes iniciais mostram que isso é confiável, mas parece um ataque desagradável.

Estou sentindo que MemoryCache e OutputCache não são necessários para trabalhar com o MVC 3 …

Então, aqui estão algumas novidades. Analisamos isso e sim, isso é um bug no .NET 4.

A boa notícia é que ele foi corrigido no .NET 4.5, portanto, se você puder, atualize sua instalação para o .NET 4.5 e estará sólido.

A outra boa notícia é que essa correção foi transferida para o .NET 4 e estará disponível como QFE (Quick Fix … uma correção que você aplicará) # 578315. Foi backported / fixo apenas alguns dias atrás e deve ser lançado o mais rápido possível. Vou tentar conseguir uma data exata, mas é em breve.

A outra outra boa notícia é que há uma solução alternativa para isso no .NET 4 antes do QFE. A solução alternativa é estranha, mas pode desbloquear você.

 using (ExecutionContext.SuppressFlow()) { // Create memory cache instance under disabled execution context flow return new YourCacheThing.GeneralMemoryCache(…); } 

Espero que isto ajude.

ATUALIZAÇÃO: O Hotfix é http://support.microsoft.com/kb/2828843 e você pode solicitá-lo aqui: https://support.microsoft.com/contactus/emailcontact.aspx?scid=sw;%5BLN%5D; 1422

Nós temos o mesmo problema. Eu confirmo que depois de algum período de tempo, o cache foi descartado. É campo privado _disposto tornou-se 1. Tenho certeza de que eu não tenho chamada para cache.Dispose no meu código. Mas quando eu olhei para o código do MemoryCache com Reflector eu vi, que no construtor ele assina em dois events

 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(); } 

Ambos os manipuladores de events têm chamada para Dispose. Pode ser depois de algum domínio recyclerview no IIS faz com que o domínio descarregar, mas mantém o cache na memory (eu não tenho certeza se é possível).

Eu tenho experimentado exatamente os mesmos sintomas. Eu finalmente consegui usar a class System.Web.Cache em vez disso e conectando em HttpContext.Cache. Tem funcionado perfeitamente nos últimos 3 dias ..

Veja também esses links relacionados ao mesmo problema.

MemoryCache é descartado após PollingInterval quando usado no WebApp no ​​modo Pipeline Integrado

http://connect.microsoft.com/VisualStudio/feedback/details/764911/memorycache-gets-disposed-after-pollinginterval-when-used-in-webapp-in-integrated-pipeline-mode

MemoryCache entra no estado Disposed Magically

http://social.msdn.microsoft.com/Forums/pt-BR/netfxbcl/thread/1233ffb3-6480-431b-94ca-1190f96cf5f6

O MemoryCache irá automaticamente MemoryCache itens se atingir seu limite de memory. Isso pode estar acontecendo no seu caso, você tem muitos itens no cache?

Você pode controlar os limites com a configuração . Por padrão, otimiza com base na memory disponível.

Certamente, chamar Dispose interromperá a instância do MemoryCache pois ele limpará todos os resources não gerenciados prontos para o descarte. Você só deve chamar Dispose se não pretender mais usar o MemoryCache . Eu não acho que isso seja necessário no seu caso, a não ser quando você liga.