将不同的值添加到并发字典中的列表中

时间:2020-10-10 15:41:04

标签: c# multithreading linq thread-safety

我尝试将小数添加到ConcurrentDictionary内的列表中

ConcurrentDictionary<string, List<decimal>> fullList =
    new ConcurrentDictionary<string, List<decimal>>();

public void AddData(string key, decimal value)
{
    if (fullList.ContainsKey(key))
    {
        var partialList = fullList[key];
        partialList.Add(value);
    }
    else
    {
        fullList.GetOrAdd(key, new List<decimal>() { value });
    }
}

从技术上讲,上面的代码对我有用,但之所以这样做,是因为我不知道如何添加和更新GetOrAdd方法。我的问题是,考虑到我的更新将在现有列表的末尾添加项目,我该如何同时使用该方法?

3 个答案:

答案 0 :(得分:2)

您可以为此使用AddOrUpdate方法,如下所示:

fullList.AddOrUpdate(key, 
                     new List<decimal>() { value }, 
                     (key,list) => 
                     { 
                         list.Add(value); 
                         return list; 
                     });

基本上,当key 缺失时,将创建一个仅包含一个元素value的新列表。否则,我们将添加到与当前keyvalue关联的列表中,然后返回列表。

有关此方法的文档,请查看here

答案 1 :(得分:1)

您是否正在寻找类似的东西?希望对您有所帮助。

    ConcurrentDictionary<string, List<decimal>> fullList = new ConcurrentDictionary<string, List<decimal>>();
    public void AddData(string key, decimal value)
    {
        List<decimal> list;
        if (!fullList.TryGetValue(key, out list))
        {
            list = new List<decimal>();
            fullList.GetOrAdd(key, list);
        }
        list.Add(value);
    }

答案 2 :(得分:0)

在所有情况下,您只需要调用GetOrAdd

public void AddData(string key, decimal value)
{
    var partialList = fullList.GetOrAdd(key, _ => new List<decimal>());
    lock (partialList) partialList.Add(value); // Lock for thread safety
}

使用ConcurrentDictionary时,您应该努力使用其特殊的并发API,以强制执行操作的原子性。分两步进行检查和添加(ContainsKey + Add)不是原子的,它引入了竞争条件,并可能损害应用程序的正确性。

相关问题