Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对ConcurrentDictionary的线程安全更改_C#_Parallel Processing_Task Parallel Library_Parallel.foreach_Concurrentdictionary - Fatal编程技术网

C# 对ConcurrentDictionary的线程安全更改

C# 对ConcurrentDictionary的线程安全更改,c#,parallel-processing,task-parallel-library,parallel.foreach,concurrentdictionary,C#,Parallel Processing,Task Parallel Library,Parallel.foreach,Concurrentdictionary,我正在并行地填充ConcurrentDictionary。ForEach循环: var result = new ConcurrentDictionary<int, ItemCollection>(); Parallel.ForEach(allRoutes, route => { // Some heavy operations lock(result) { if (!result.ContainsKey(someKey))

我正在并行地填充
ConcurrentDictionary
。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);
    }
}
var result=新的ConcurrentDictionary();
Parallel.ForEach(所有路由,路由=>
{
//一些重大行动
锁定(结果)
{
如果(!result.ContainsKey(someKey))
{
结果[someKey]=新的ItemCollection();
}
结果[someKey]。添加(newItem);
}
}
如何在不使用lock语句的情况下以线程安全的方式执行最后的步骤

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

我认为您需要,它被明确设计为获取现有项,或者在给定键没有条目时添加新项

var collection = result.GetOrAdd(someKey, _ => new ItemCollection());
collection.Add(newItem);
如问题注释中所述,这假设
ItemCollection
是线程安全的。

您需要使用该方法

var result=新的ConcurrentDictionary();
int someKey=。。。;
var newItem=。。。;
ItemCollection=result.GetOrAdd(someKey,=>newitemcollection());
collection.Add(newItem);

假设
ItemCollection.Add
不是线程安全的,您将需要一个锁,但您可以减小关键区域的大小

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

lock(collection)
    collection.Add(...);
更新:因为它看起来是线程安全的,所以根本不需要锁

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

ItemCollection.Add
线程安全吗?如果不是,你需要一个锁。@ken2k:除非我的情况有一个条件元素。如果密钥不存在,请创建一个新的
ItemCollection
,否则在该密钥处向现有的
ItemCollection
添加一个项目。@dcastro:是的,请假设ItemCollection是线程安全的。这可能不像看上去那么安全:@jeffdot:我认为在这种情况下这不是一个问题-在任何锁中都不需要调用
ItemCollection
构造函数…你设想的是什么问题?因为有关于锁定的讨论,而且因为
ConcurrentDictionary
确实有一个内部锁,我觉得我们是通过让人们认为
GetOrAdd
AddOrUpdate
是原子的或在字典的锁内调用,增加了风险。我注意到,您给出了公平的警告,即
ItemCollection
必须是线程安全的。OP回复了您的评论,说ItemCollection是线程安全的。@JonSkeet谢谢,没有注意到。
var collection = result.GetOrAdd(someKey, k => new ItemCollection());
collection.Add(...);