MemoryCache Empty:设置后返回null

时间:2011-09-14 20:55:00

标签: asp.net .net asp.net-mvc caching memorycache

我遇到了使用新的.NET 4 System.Runtime.Caching MemoryCache的MVC 3应用程序的问题。我注意到在看似无法预测的时间之后,它会停止缓存,并且表现得像空的一样。考虑一下我直接从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"]的值为空。我可以通过在Response.Write()行设置断点并使用立即窗口直接设置和读取缓存来证明这一点 - 它不会设置它并保持为空!然后,让它再次运行的唯一方法是使AppDomain回收。

有趣的是,通过打破Response.Write()行并运行MemoryCache.Default.Dispose(),我可以在应用正常工作时引发问题。之后,MemoryCache.Default本身不为null(为什么会这样?),但不保存任何设置。它不会导致任何错误,但不会保存任何内容。

有人可以验证并解释吗?我相信我已经发现,当应用程序停止工作时,某些正在处理MemoryCache.Default,但这不是我!


更新

好吧,我现在厌倦了这个问题! CLRProfiler似乎不适用于MVC 3.SciTech的CLR工具很好 - RedGate ANTS也是如此。但是他们告诉我的只是MemoryCache对象被某些东西处理掉了!我还证明了(通过时间戳打印)我的页面上应该被缓存的部分视图(由OutputCacheAttribute指定)在几分钟后停止缓存 - 它会在每次调用页面时开始刷新。为了澄清环境,我直接在运行Win 7 Ultimate的开发工作站上的IIS 7.5服务器上运行。上面提到的内存工具表明我只使用大约9mb的内存来处理游戏。

在绝望中我已经改变了我的缓存代码,首先搜索环境HttpContext以挂钩并使用其缓存功能(如果有的话)。早期测试表明这是可靠的,但感觉就像一个讨厌的黑客。

我觉得MemoryCache和OutputCache不能保证与MVC 3一起工作......

5 个答案:

答案 0 :(得分:68)

所以,这是一些新闻。我们调查了这个,是的,这是.NET 4中的一个错误。

好消息是它已经在.NET 4.5中得到修复,所以如果可以,请将您的安装更新到.NET 4.5,然后就可以了。

另一个好消息是,这个修复程序已经被移植到.NET 4并将作为QFE提供(快速修复......一次性修复,你将适用)#578315。它是在几天前被移植/修复的,它应该尽快出来。我会尽力确定一个确切的日期,但很快就会到来。

另一个好消息是,在QFE之前,.NET 4上有一个解决方法。解决方法很奇怪,但它可以解锁你。

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

答案 1 :(得分:6)

我们遇到同样的问题。我确认一段时间后缓存被处理掉了。它的私有字段_disposed变为1.我确信我没有调用cache.Dispose在我的代码中。但是当我看到带有Reflector的MemoryCache代码时,我看到,在构造函数中它订阅了两个事件

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中进行了一些域名回收后,它会导致域名卸载,但会将缓存保留在内存中(如果可能的话,我不会这么做)。

答案 2 :(得分:3)

我一直在经历完全相同的症状。我最终导致使用System.Web.Cache类并挂钩到HttpContext.Cache。它在过去的3天里一直运作良好..

答案 3 :(得分:2)

另请参阅与同一问题相关的这些链接。

当在集成管道模式下的WebApp中使用时,MemoryCache在PollingInterval之后被释放

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

MemoryCache神奇地进入处置状态

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

答案 4 :(得分:1)

如果MemoryCache达到内存限制,Dispose将自动逐出。在您的情况下可能会发生这种情况,缓存中是否有很多项目?

您可以使用configuration控制限制。默认情况下,它会根据可用内存进行优化。

当然,调用MemoryCache将阻止Dispose实例正常工作,因为它将清理所有准备好处理的非托管资源。如果您不打算再使用MemoryCache,则只应致电{{1}}。除了你打电话的时候,我不认为你的问题是必要的。