Skip to content

Instantly share code, notes, and snippets.

@pseudomuto
Created August 25, 2013 17:19
Show Gist options
  • Save pseudomuto/6335102 to your computer and use it in GitHub Desktop.
Save pseudomuto/6335102 to your computer and use it in GitHub Desktop.
Blog Code: Efficient Thread-Safe Caching with ASP.NET
public class CacheManager
{
// CLR guarantees thread-safety during initialization
private static Dictionary<string, object> CacheKeyDictionary = new Dictionary<string, object>();
public static TObj GetCachedObject<TObj>(string cacheKey, Func<TObj> creator) where TObj : class
{
var cache = HttpContext.Current.Cache;
var obj = cache[cacheKey] as TObj;
if (obj == null)
{
// get the lock object
var lockObject = GetCacheLockObject(cacheKey);
lock (lockObject)
{
// double check...if-lock-if
obj = cache[cacheKey] as TObj;
if (obj == null)
{
obj = creator.Invoke();
cache.Insert(cacheKey, obj);
}
}
}
return obj;
}
private static object GetCacheLockObject(string cacheKey)
{
if (!CacheKeyDictionary.ContainsKey(cacheKey))
{
// lock on the whole dictionary
lock (CacheKeyDictionary)
{
// check again...always remember: if-lock-if
if (!CacheKeyDictionary.ContainsKey(cacheKey))
{
CacheKeyDictionary.Add(cacheKey, new object());
}
}
}
return CacheKeyDictionary[cacheKey];
}
}
private IEnumerable<string> GetExpensiveNameList()
{
return CacheManager.GetCachedObject<IEnumerable<string>>(
"CacheKeyHere",
() =>
{
// perform expensive lookup here...
return Enumerable.Empty<string>();
}
);
}
private TObj GetCachedObject<TObj>(string cacheKey, Func<TObj> creator) where TObj : class
{
Cache cache = this.HttpContext.Cache;
TObj obj = cache[cacheKey] as TObj;
if (obj == null)
{
lock (cache)
{
//look it up again in case a previous request created it already
obj = cache[cacheKey] as TObj;
if (obj == null)
{
obj = creator.Invoke();
cache.Insert(cacheKey, obj);
}
}
}
return obj;
}
private TObj GetCachedObject<TObj>(string cacheKey, Func<TObj> creator) where TObj : class
{
Cache cache = this.HttpContext.Cache;
TObj obj = cache[cacheKey] as TObj;
if (obj == null)
{
lock (cache)
{
obj = creator.Invoke();
cache.Insert(cacheKey, obj);
}
}
return obj;
}
private TObj GetCachedObject<TObj>(string cacheKey, Func<TObj> creator) where TObj : class
{
TObj obj = this.HttpContext.Cache[cacheKey] as TObj;
if (obj == null)
{
obj = creator.Invoke();
this.HttpContext.Cache.Insert(cacheKey, obj);
}
return obj;
}
@adrianrosca
Copy link

Thank you very much for this! It really helped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment