开发者

System.Runtime.Caching "forgets" about caching when the debugger is attached

I have a suite of application components that require the persistence of a large business object collection in order to achieve reasonable performance. This is essentially data that is read from the database 开发者_如何转开发and hydrated into objects for later reuse.

This object collection was originally implemented in .net 3.5, so In order to achieve this persistence when loaded by an ASP.Net runtime the HttpRuntime.Cache was used, and if it was loaded by a win forms client the enterprise library caching block was used.

Now, with .net 4.0 the System.Runtime.Caching is available for these requests. The following pattern was implemented for cached item get.

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

This seems to work, but only as long as there is no debugger (vs2010) attached.

Once I attach a debugger, the cache existence check noted above always returns nothing.

These are pretty much rote examples of how to use the cache from MSDN. Is there something that I am missing, or is this truly unexpected behavior?

Update: I see this happening when the components are hosted in ASP.net. I can build the DLL's, copy them to the site, run a few executions of steps and its fine. As soon as I attach the debugger and execute the steps again, it displays this behavior.

Update 2: As often happens here, a little while after I posted the question, I got a bit more error detail from the debugger output window. This error detail led me to this MS Connect article. It turns out that when using remoting (I am) to call into an ASP.NET hosted app, the MemoryCache.Default seems to tie its janitorial timers (cache cleanup, etc) to a thread context. When the thread context is no longer available, the callbacks fail and the MemoryCache.Default appears to stop working for all other attempts.

Adding the ExecutionContext.SuppressFlow() (as seen in the reworked example below) seems to stop this attachment.

     Using ExecutionContext.SuppressFlow()

            _cache = MemoryCache.Default

     End Using

I put this in yesterday and its been peachy since.


not sure but I see the way you use the cache is a bit different from the example in MSDN, you are calling the add method instead of the Set.

Here the example I have found:

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

found here: MemoryCache Class

you also say that this problem happens when you host your components in an ASP.NET application, in ASP.NET I personally would use the HttpContext.Current.Cache it could be that this MemoryCache you are using now already does this, not sure because I have never used it before so can't tell, but how would it work if you change Add with Set and use the HttpContext's ones? Just check HpptContext.Current because it will be null if not running in an ASP.NET application.

another point you could pay attention to is, when you attach the debugger, do you really execute the Cache.Add/Set method?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜