MemoryCache Empty :设置后返回 null

Posted

技术标签:

【中文标题】MemoryCache Empty :设置后返回 null【英文标题】:MemoryCache Empty : Returns null after being set 【发布时间】:2011-11-17 09:09:49 【问题描述】:

我对使用新的 .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 (为什么会这样?),但不会保存任何设置。它不会导致任何错误,但不会保存任何内容。

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


更新

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

无奈之下,我已将缓存代码更改为首先搜索环境 HttpContext 以连接并使用其缓存功能(如果可用)。早期的测试表明这是可靠的,但感觉就像一个讨厌的 hack。

感觉 MemoryCache 和 OutputCache 不能与 MVC 3 一起使用...

【问题讨论】:

根据msdn的说法,在appdomain卸载时调用dispose方法。 msdn.microsoft.com/en-us/library/… 这似乎是正在发生的事情。但是,要为下一个 Web 请求提供服务,必须启动另一个 appdomain 实例,对吗?所以我想知道为什么 MemoryCache.Default 没有绑定到 new 不管 .net-4.0 的错误,是不是调用Set() 紧跟Get() 不正确?即使没有释放缓存,您设置的值也可能在此期间被刷新...... 【参考方案1】:

所以,这里有一些消息。我们对此进行了调查,是的,这是 .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

【讨论】:

是的,在上面编辑并在此处复制:修补程序是 support.microsoft.com/kb/2828843,您可以在这里申请:support.microsoft.com/contactus/… 我错过了什么吗?该修补程序中修复的六个问题似乎都与 MemoryCache 无关。 不,你没有错过任何东西。我正在和写那篇文章的人说话。这很糟糕,我知道,但修复就在那里,我保证。 我们已经更新了 KB 的详细信息。这是修复:support.microsoft.com/kb/2828843 如果你的配置中有 这样的东西,你可能仍然有这个错误。【参考方案2】:

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

【讨论】:

【参考方案3】:

我一直在经历完全相同的症状。我终于改用 System.Web.Cache 类并连接到 HttpContext.Cache。过去 3 天它一直运行良好..

【讨论】:

【参考方案4】:

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

在集成管道模式下的 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

【讨论】:

【参考方案5】:

MemoryCache 会在达到其内存限制时自动驱逐项目。这可能发生在您的情况下,您的缓存中有很多项目吗?

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

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

【讨论】:

这里还有一个问题。默认配置是允许缓存使用高达 98% 的可用内存,并且显然是 0.8GB 的​​硬限制。我绝对确定我最多只使用几百 Kb,但我无法找到一种方法来显示 MemoryCache 在任何时候实际使用了多少内存 - 有什么想法吗? 另外我很确定驱逐不会释放缓存实例——在这种情况下,当我添加简单的字符串“fred”时,它应该存储它,对吧? @JamesMcCormack 你找到解决方案了吗?我遇到了同样的问题,我注意到这个答案已被接受,但我不确定你是否真的找到了解决方案。 谢谢。不得不添加这种依赖是令人沮丧的,我也希望避免这种情况。希望这个错误能很快得到解决,因为它使内存缓存或多或少没用。 我也有同样的问题...内存缓存被神奇地处理掉了

以上是关于MemoryCache Empty :设置后返回 null的主要内容,如果未能解决你的问题,请参考以下文章

MemoryCache AbsoluteExpiration 行为奇怪

MemoryCache 的大小设置是啥意思?

MemoryCache获取/设置并分配给变量

MemoryCache.AddOrGetExisting 有啥用?

停止 MemoryCache 调用的重入

MemoryCache使用方法