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:
static System.Web.Caching.Cache _memoryCache;private
// 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