it-swarm.cn

MemoryCache Empty:设置后返回null

我有一个使用新的.NET 4 System.Runtime.Caching MemoryCache的MVC 3应用程序的问题。我注意到在看似无法预测的时间之后,它会停止缓存,并且表现得像空的一样。考虑一下我直接从ASP.NET MVC中的测试View获取的代码:

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()行上设置断点并使用立即窗口直接设置和读取缓存来证明这一点 - 它只是不会设置它并保持为空!让它再次运行的唯一方法是使AppDomain回收。

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

任何人都可以验证并解释吗?我相信我已经发现,当应用程序停止工作时, 某事 是Disposing MemoryCache.Default,但不是我!


_ update _

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

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

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

50
James McCormack

所以,这是一些新闻。我们调查了这个,是的,这是.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

68
Scott Hanselman

我们有同样的问题。我确认一段时间后缓存被处理掉了。它的私有字段_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中的一些域名回收之后_它会导致域名卸载,但会将缓存保留在内存中(如果可能的话,我不会保留)。

6
Dima

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

3
Grant

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

在集成管道模式下的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神奇地进入Disposed状态

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

2
Alex Nolasco

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

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

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

1
TheCodeKing