Weird MemoryCache problem RRS feed

  • Question

  • User-101626319 posted

    Don't know if this is the correct forum, please guide me if it is not.

    I have a bunch of webservices that use memoryCache.default to store information. I have a weird problem where the cache sometimes appears to be empty even if it is not. A simplified scenario:

    1. One webservice is called to start a rather long process (several minutes). The webservice sets some cache entries and start the long process as a parallel thread and then return to the client. The webservice stores two items in the MemoryCache.default cache; one item with a sliding expiration of 5 minutes the other item is permanently stored. After the items have being stored in the cache, an enumeration of the cache items shows that they are really there, both of them.

    2. The client polls another webservice once a second to get updated information about the statsu of the started long process. The webservice check the existence of the permanent item, and creates it if it is missing in the cache (in fact this is the same code as created the item in the first call). This works for a while, but eventially it fails, and the cache is reported to be empty.  MemoryCache.Default.Contains(item) return false. MemoryCache.Default.Set(item,...) does not store the item in the cache. After the call the cache is still reported as being empty.

    3. Eventually, the sliding expiration item expires, and the defined RemovedCallback is called. Obviously, the cache was not empty after all since this item existed and expired.

    All items are created with callbacks that tell if something happens to the item (all calls are logged).  All actions are logged including thread ID and AppDomain ID. The execution in pt 2 above is of course on a separate thread. Everything is performed in the same AppDomain. No calls to RemovedCallbacks are made for the permanent items. So, the AppDomain isn't disposed since I'm in teh same AppDomain all way through. The items aren't removed since I get no RemoveCallback. It's like I'm suddenly working with another Cache, but I'm still in teh same AppDomain...

    Why can't the thread in pt 2 see the content of MemoryCache.Default? Why can' the thread in pt 2 store anything in MemoryCache.Default?

    public static GlobalCatalog CurrentGlobalCatalog
    		if (!MemoryCache.Default.Contains("CurrentGlobalCatalog"))
    			CacheItemPolicy cip = new CacheItemPolicy()
    				SlidingExpiration = new TimeSpan(0, 5, 0),
    				RemovedCallback = GlobalCatalogRemovedCallback, 
    				Priority = System.Runtime.Caching.CacheItemPriority.Default
    			MemoryCache.Default.Set(new CacheItem("CurrentGlobalCatalog", CurrentForest.FindGlobalCatalog()), cip);
    			Utils.Log(TraceEventType.Verbose, string.Format("CurrentGlobalCatalog: {0}, AppDOmain: {1}", ((GlobalCatalog)MemoryCache.Default["CurrentGlobalCatalog"]).Name, AppDomain.CurrentDomain.Id.ToString()));
    		return (GlobalCatalog)MemoryCache.Default["CurrentGlobalCatalog"];
    public static SecurityIdentifier ReaderSID
    		if (!MemoryCache.Default.Contains("PKIReaderSID"))
    			CacheItemPolicy cip = new CacheItemPolicy()
    				AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
    				Priority = System.Runtime.Caching.CacheItemPriority.Default,
    				UpdateCallback = Utils.CacheUpdateCallback,
    			MemoryCache.Default.Set("PKIReaderSID", GetSID(ReaderGroup), cip);
    			Utils.Log(System.Diagnostics.TraceEventType.Information, string.Format("Reader group='{0}', SID='{1}'", ReaderGroup, (SecurityIdentifier)MemoryCache.Default["PKIReaderSID"]));
    		return (SecurityIdentifier)MemoryCache.Default["PKIReaderSID"];
    Thursday, November 3, 2011 3:43 PM

All replies

  • User-1170981957 posted

    It sounds like your problem may require a more in-depth level of support. Please visit the below link to see the various paid support options that are available to better meet your needs. http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone

    Friday, November 18, 2011 4:47 AM
  • User903505751 posted
    Were you able to solve this problem? I'm having a similar issue in an ASP.NET MVC3 web application. After 2 minutes the cache stops working, I'm not able to retrieve anything from it.
    Tuesday, April 10, 2012 2:07 PM
  • User-101626319 posted

    Unfortunately not. The cache is sometimes empty, sometimes not, and I found no clue to why this happens. I use the cache only to enhance performance, and I was forced to code the cache retrieval in a fail-safe way. If the expected item is in the cache I use it, otherwise I create a new instance and take the performace hit.

    Tuesday, April 10, 2012 2:30 PM
  • User-481631678 posted

    Try replacing your check like this:-

    if (!MemoryCache.Default.Contains("CurrentGlobalCatalog")

    Wednesday, April 11, 2012 10:20 AM
  • User-101626319 posted

    Thanks for the tip, but the problems isn't the the technique to check for item existance.

    I have debugged the thing. Everytime the problem occur, the MemoryCache is indeed completely empty. No matter how I ivestigate it with Visual Studio in the breakpoint, it has a "newly initlized" state. In fact - if some threads were indeed working with a completely different instantiation of the Memorycache, this is exactly what it would look like.

    And the mystery is that the cache is *not* cleared. If I run a number of threads in the same program, some threads will work with the "real" cache and will have  acess to the items in the cache. Other threads (in a random pattern from what I can see) run exactly the same code lines, but work with an initialized cache with no items at all. Later on, threads are suddenly working with the initial, correct cache that still holds the items I put in it in the beginning.

    BTW - the project havin these problems isn't in use any more, so I have a hard time reproducing the situation and get additional linformation. The answer above is based on the work I did while the project was still in an active stat.

    Wednesday, April 18, 2012 4:39 PM
  • User175249580 posted

    The problem is that you are assuming the item you are assigning to the cache has indeed been placed in the cache.  When there is no room (or perhaps more accurately not a certain percentage of memory available), the item will not be placed in the cache.

    When an item does not exist in the cache, retrieve the item into a variable, assign the variable to the cache, and then return the VARIABLE.

    Tuesday, October 16, 2012 3:44 PM