我有一个Dictionary(并发),用于将一个对象id映射到另一个。根据输入键获取值id相当昂贵,因此我希望将字典保留在服务器缓存中。
我首先尝试了一种方法来做到这一点,但它只是“觉得”可能有更好的方法来做到这一点:
private string GetItem(string cacheKey, string itemKey)
{
string sfAccountId = null;
ConcurrentDictionary<string, string> sfAccountMap =
Context.Cache[cacheKey] as ConcurrentDictionary<string, string>;
if(sfAccountMap == null)
{
lock(cacheLock)
{
sfAccountMap = Context.Cache[cacheKey] as ConcurrentDictionary<string, string>;
if(sfAccountMap == null)
{
sfAccountMap = new ConcurrentDictionary<string, string>();
sfAccountId = ExpensiveMethodReturnsString();
if(!String.IsNullOrEmpty(sfAccountId))
{
sfAccountMap.TryAdd(itemKey, sfAccountId);
}
Context.Cache[cacheKey] = sfAccountMap;
}
}
}
else
{
if(sfAccountMap.ContainsKey(itemKey))
{
sfAccountMap.TryGetValue(itemKey, out sfAccountId);
}
else
{
sfAccountMap.TryAdd(itemKey, ExpensiveMethodReturnsString());
lock(cacheLock)
{
Context.Cache[cacheKey] = sfAccountMap;
}
}
}
return sfAccountId;
}
答案 0 :(得分:1)
看起来您的代码可以简化,同时仍然可以执行它现在正在执行的操作。
private ConcurrentDictionary<string, string> GetCachedAccountMap(string cacheKey)
{
var map = Context.Cache[cacheKey] as ConcurrentDictionary<string, string>;
if (map == null)
{
lock (cacheLock)
{
map = Context.Cache[cacheKey] as ConcurrentDictionary<string, string>;
if (map == null)
map = Context.Cache[cacheKey] = new ConcurrentDictionary<string, string>();
}
}
return map;
}
private string GetItem(string cacheKey, string itemKey)
{
return GetCachedAccountMap(cacheKey)
.GetOrAdd(itemKey, k => ExpensiveMethodReturnsString());
}
注意:鉴于帐户映射尚不存在时,不太可能同时访问缓存,并且在非常特殊的情况下,如果您执行一次额外的分配并调用昂贵的方法,GetCachedAccountMap
方法可以通过不使用任何锁来进一步简化。
private ConcurrentDictionary<string, string> GetCachedAccountMap(string cacheKey)
{
var map = Context.Cache[cacheKey] as ConcurrentDictionary<string, string>;
if (map == null)
map = Context.Cache[cacheKey] = new ConcurrentDictionary<string, string>();
return map;
}