Here I want to lock when populating a particular cache object, without blocking other calls to the same method requesting Foo
s for other barId
s. I realise the MemoryCache
will be thread safe, but if two or more concurrent calls come in it seems like it would be better if only one of them populates the cache and locks the others out while this is done.
using System.Runtime.Caching;
using Microsoft.Practices.Unity;
public class FooCacheService : IFooService
{
private static readonly ConcurrentDictionary<string, object> FooServiceCacheLocks = new ConcurrentDictionary<string, object>();
[Dependency("Explicit")]
public IFooService ExplicitService { get; set; }
public IEnumerable<Foo> GetFoosForBar(int barId)
{
string key = barId.ToString();
object lockObject = FooServiceCacheLocks.GetOrAdd(key, new object());
object cached = MemoryCache.Default[key];
if (cached == null)
{
lock (lockObject)
{
cached = MemoryCache.Default[key];
if (cached == null)
{
IEnumerable<Foo> foosForBar = this.ExplicitService.GetFoosForBar(barId);
MemoryCache.Default.Add(key, foosForBar, DateTime.Now.AddMinutes(5));
return foosForBar;
}
}
}
return (IEnumerable<Foo>)cached;
}
}
Assume GetFoosForBar
is a CPU/IO intensive process and takes a short while to complete. Does this seem like a reasonable way to achieve this? I'm surprised that System.Runtime.Caching
does not provide any support for this as default - or have I overlooked something?