Wednesday, September 1, 2004

169.aspx

Using the ASP.NET cache from …. anywhere


Once upon a time….


I needed a smart way to cache data in memory. It should have a fixed expire date but also be smart enough to delete items that were not used in a long time. Frist I implemented a very simple system using a HashTable with a garbage collection thread.


A simplified version:



private static System.Collections.Hashtable _memoryCollection = new System.Collections.Hashtable();



public void setItem(CacheItem cacheItem)

   _memoryCollection[cacheItem.cacheID] = cacheItem;
}


public CacheItem getItem(string cacheID)

   CacheItem cacheItem = (CacheItem) _memoryCollection[cacheID];

  
if (null != cacheItem)
   {
      
// Note; no interlocked. Who cares if we loose a hit or two
      
cacheItem.usageCount++;
   }
   
return cacheItem;
}


A garbage collector can be scheduled using::



System.Threading.Thread thread = new Thread(new ThreadStart(garbageCollector));
thread.Start();


Which does something like this:




System.DateTime now = System.DateTime.Now;
System.Collections.ArrayList itemsToDelete =
new System.Collections.ArrayList();


foreach (DictionaryEntry item in _memoryCollection)
{
  CacheItem cacheItem = (CacheItem) item.Value;


  if (cacheItem.expireDate < now || 0 == cacheItem.usageCount)
  {
    itemsToDelete.Add (item.Key);
  }
  else
  {
    
// Use this if you really care: Interlocked.Exchange(cacheItem.usageCount, 0); 
    
cacheItem.usageCount = 0;
  }
}


// Delete the items
foreach (string key in itemsToDelete)
{
   _memoryCollection.Remove(key);
}


 


Then I saw the light and used the ASP.NET built in cache. The really cool thing is that it works from anywhere; asp.net, a standalone .exe, a .net component registered in com+ (i.e. inherits from EnterpriseServices). And it gives you garbage collection, sliding and fixed expire etc for free


The clue is not to hit the stones together but to add a reference to System.Web.dll and use the System..Web.HttpRuntime.Cache to get a reference to the Asp.net cache.


Example:



private static System.Web.Caching.Cache _memoryCache;

// Somewhere:
_memoryCache = System.Web.HttpRuntime.Cache;


public void setItem(CacheItem cacheItem)

   _memoryCache.Insert(cacheItem.cacheID, cacheItem.cacheValue, null, cacheItem.expireDate, System.Web.Caching.Cache.NoSlidingExpiration, cacheItem.priority, null);
}


public CacheItem.getItem(string cacheID)

   return  (CacheItem) _memoryCache.Get(cacheID);
}


YMMV but I hope the code above gives the idea.


 

No comments:

Post a Comment