Skip to content

Instantly share code, notes, and snippets.

@pseudomuto
Created August 25, 2013 17:19
Show Gist options
  • Select an option

  • Save pseudomuto/6335102 to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

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