对ConcurrentDictionary的线程安全更改

时间:2014-06-12 13:17:01

标签: c# parallel-processing task-parallel-library parallel.foreach concurrentdictionary

我在ConcurrentDictionary循环中填充Parallel.ForEach

var result = new ConcurrentDictionary<int, ItemCollection>();

Parallel.ForEach(allRoutes, route => 
{
    // Some heavy operations

    lock(result)
    {
        if (!result.ContainsKey(someKey))
        {
            result[someKey] = new ItemCollection();
        }

        result[someKey].Add(newItem);
    }
}

如何在不使用lock语句的情况下以线程安全的方式执行最后的步骤?

编辑:假设ItemCollection是线程安全的。

3 个答案:

答案 0 :(得分:4)

我认为您需要GetOrAdd,明确设计用于获取现有项目,或者如果给定密钥没有条目,则添加新项目。

var collection = result.GetOrAdd(someKey, _ => new ItemCollection());
collection.Add(newItem);

如问题评论中所述,这假设ItemCollection是线程安全的。

答案 1 :(得分:1)

您需要使用GetOrAdd方法。

var result = new ConcurrentDictionary<int, ItemCollection>();

int someKey = ...;
var newItem = ...;

ItemCollection collection = result.GetOrAdd(someKey, _ => new ItemCollection());
collection.Add(newItem);

答案 2 :(得分:1)

假设ItemCollection.Add不是线程安全的,需要锁定,但可以减少关键区域的大小。

var collection = result.GetOrAdd(someKey, k => new ItemCollection());

lock(collection)
    collection.Add(...);

更新:因为它似乎是线程安全的,所以你根本不需要锁定

var collection = result.GetOrAdd(someKey, k => new ItemCollection());
collection.Add(...);