1

我有一套应用程序组件,它们需要大型业务对象集合的持久性才能实现合理的性能。这本质上是从数据库中读取并混合成对象以供以后重用的数据。

这个对象集合最初是在 .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

我昨天把这个放进去的,从那以后它就很漂亮了。

4

1 回答 1

0

不确定,但我看到您使用缓存的方式与 MSDN 中的示例有点不同,您调用的是 add 方法而不是 Set。

这是我找到的示例:

Private Sub btnGet_Click(ByVal sender As Object, ByVal e As EventArgs) 
    Dim cache As ObjectCache = MemoryCache.[Default] 
    Dim fileContents As String = TryCast(cache("filecontents"), String) 

    If fileContents Is Nothing Then 
        Dim policy As New CacheItemPolicy() 
        Dim filePaths As New List(Of String)() 
        filePaths.Add("c:\cache\example.txt") 

        policy.ChangeMonitors.Add(New HostFileChangeMonitor(filePaths)) 

        ' Fetch the file contents.
        fileContents = File.ReadAllText("c:\cache\example.txt") 

        cache.[Set]("filecontents", fileContents, policy) 
    End If 

    Label1.Text = fileContents
End Sub

在这里找到:MemoryCache 类

您还说当您在 ASP.NET 应用程序中托管组件时会发生此问题,在 ASP.NET 中我个人会使用HttpContext.Current.Cache它可能是您现在使用的这个 MemoryCache 已经这样做了,不确定因为我从未使用过它之前所以不能说,但是如果你用 Set 改变 Add 并使用 HttpContext 的,它会如何工作?只需检查 HpptContext.Current,因为如果不在 ASP.NET 应用程序中运行,它将为空。

另一点需要注意的是,当你附加调试器时,你真的执行了 Cache.Add/Set 方法吗?

于 2011-09-12T20:31:36.603 回答