我有一套应用程序组件,它们需要大型业务对象集合的持久性才能实现合理的性能。这本质上是从数据库中读取并混合成对象以供以后重用的数据。
这个对象集合最初是在 .net 3.5 中实现的,所以为了在 ASP.Net 运行时加载时实现这种持久性,使用了 HttpRuntime.Cache,如果它是由 win 表单客户端加载的,则使用企业库缓存块.
现在,在 .net 4.0 中,System.Runtime.Caching 可用于这些请求。为缓存项获取实现了以下模式。
Public Function GetCachedObject(cacheKey as String) as Object
Dim _returnValue as Object
SyncLock m_lockObject //some private lock object
Dim _cache as ObjectCache = MemoryCache.Default
//This is never found when debugging
If _cache.Item(cacheKey) IsNot Nothing Then
_returnValue = _cache.Item
Else
Dim _policy As New System.Runtime.Caching.CacheItemPolicy()
_policy.AbsoluteExpiration = DateTime.Now.AddHours(12)
Dim _obj as Object = MethodToGetAndHydrateObject()
_cache.Add(New CacheItem(cacheKey, _obj), _policy)
_returnValue = _obj
End If
End SyncLock
Return _returnValue
End Function
这似乎可行,但前提是没有附加调试器(vs2010)。
一旦我附加了一个调试器,上面提到的缓存存在检查总是什么都不返回。
这些都是关于如何使用 MSDN 中的缓存的死记硬背的例子。是否有我遗漏的东西,或者这是真正出乎意料的行为?
更新:当组件托管在 ASP.net 中时,我看到这种情况发生。我可以构建 DLL,将它们复制到站点,运行一些步骤,并且很好。一旦我附加调试器并再次执行这些步骤,它就会显示此行为。
更新 2:正如这里经常发生的那样,在我发布问题后不久,我从调试器输出窗口中获得了更多错误细节。这个错误细节让我看到了这篇MS Connect 文章。事实证明,当使用远程处理(我是)调用 ASP.NET 托管应用程序时,MemoryCache.Default 似乎将其看门计时器(缓存清理等)绑定到线程上下文。当线程上下文不再可用时,回调失败并且 MemoryCache.Default 似乎停止为所有其他尝试工作。
添加 ExecutionContext.SuppressFlow() (如下面的重做示例所示)似乎停止了这个附件。
Using ExecutionContext.SuppressFlow()
_cache = MemoryCache.Default
End Using
我昨天把这个放进去的,从那以后它就很漂亮了。