Ok, so I'm querying a webservice. This webservice is slow with multiple o's. I want to cache the results of the query, because I only want to query on a given set of parameters once during my transaction (In addition to the query being slow, it's also rate limited, so I don't want to perform unnecessary queries). Finally, to speed things up, I want to be able to run queries in parallel, as latency is my biggest problem here.
With all of that, I think I need a thread safe way to cache data and only run the queries I actually need to run. I think I've managed to cobble that together with Concurrent Dictionary and Lazy
private static ConcurrentDictionary<KeyObject, Lazy<IEnumerable<ValueObject>>> DataCache =
new ConcurrentDictionary<KeyObject, Lazy<IEnumerable<ValueObject>>>();
public static IEnumerable<ValueObject> GetData(KeyObject key, QueryObject query)
{
var value = new Lazy<IEnumerable<ValueObject>>(() =>
{
return query.Run();
});
DataCache.TryAdd(key, value);
return DataCache[key].Value;
}
}
If I'm correct in understanding how all the moving parts work, it should go something like this.
- Generate dictionary key and Lazy intializer for value
- Try and add lazy initializer to dictionary with key. If another thread has already added key, fail and continue.
- Try and get value of lazy intializer on record in the dictionary. If another thread is already getting value, block until other thread has retrieved value.
Does this sound correct?