Jam*_*ack 51 .net asp.net asp.net-mvc caching memorycache
我有一个使用新的.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"]);
Run Code Online (Sandbox Code Playgroud)
当它工作时,可预测的"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对象被某些东西处理掉了!我还证明了(通过时间戳打印)我的页面上应该被缓存的部分视图(由OutputCacheAttribute指定)在几分钟后停止缓存 - 它会在每次调用页面时开始刷新.为了澄清环境,我直接在运行Win 7 Ultimate的开发工作站上的IIS 7.5服务器上运行.上面提到的内存工具表明我在播放对象方面只使用了大约9mb的内存.
无奈之下,我已经改变了我的缓存代码,首先搜索环境HttpContext以挂钩并使用其缓存功能(如果有的话).早期测试显示这是可靠的,但感觉就像一个讨厌的黑客.
我觉得MemoryCache和OutputCache不能保证与MVC 3一起工作......
Sco*_*man 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(…);
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
更新:修补程序是http://support.microsoft.com/kb/2828843,您可以在此处请求:https://support.microsoft.com/contactus/emailcontact.aspx?scid = sw;%5BLN%5D; 1422
我们有同样的问题.我确认一段时间后缓存被处理掉了.它的私有字段_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();
}
Run Code Online (Sandbox Code Playgroud)
这两个事件处理程序都调用了Dispose.可能是在IIS中进行一些域名回收之后,它会导致域名卸载,但会将缓存保留在内存中(如果可能的话,我不会这么做).