【问题标题】:Accessing and Updating Cached Dictionary访问和更新缓存字典
【发布时间】:2015-04-01 18:30:03
【问题描述】:

我有一个字典(并发),用于将一个对象 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;
}

【问题讨论】:

    标签: c# asp.net .net concurrency


    【解决方案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;
    }
    

    【讨论】:

    • 啊,是的,看起来更好。
    猜你喜欢
    • 1970-01-01
    • 2013-08-27
    • 2019-09-13
    • 2013-04-16
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    • 2017-06-12
    • 1970-01-01
    相关资源
    最近更新 更多