22 Jun 2010

On my current project, we need to cache some of the results retreived when querying into SharePoint. As the retrieving operation is quite expensive (as always with SharePoint) and that performances are very important, we must make sure that it is only executed once.

So, the way to do this is to use the double check locking mechanism. The idea is to check if the cache contains the item sought, if it does not contain it, lock then check again, in case another thread added it while we were acquiring the lock.

I wrote a generic extension method to do this, to which the lock handle to lock on is given as a parameter, as well as the function used to retrieve the item if it is not in the cache. In this case, the retrieved item will be stored in the cache (and of course returned to the called).

Code speaks louder than words:

public static class CacheExtension
{
    public static T SetAndGetItemFromCache<T>(this Cache cache, String cacheKey, Object lockHandle, Func<Cache, T> addItemToCache)
    {
        Object item = cache.Get(cacheKey);

        if (item == null)
        {
            lock (lockHandle)
            {
                item = cache.Get(cacheKey);

                if (item == null)
                {
                    item = addItemToCache(cache);
                }
                else
                {
                    //The sought item has been added meanwhile in another thread/process
                }
            }
        }
        else
        {
            //Cache contains the key, return it
        }

        if (item is T)
        {
            return (T)item;
        }
        else
        {
            //The Object in the cache is not of type T, some other component might be using that key
             throw new ApplicationException(String.Format("Object retreived from the cache is not of the expected {0} type. Another component might be using the same key to store in the cache.", typeof(T).FullName));
        }
    }
}

This can be used on any System.Web.Caching.Cache object.



blog comments powered by Disqus