2

ループConcurrentDictionary内にaを入力しています: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スレッドセーフ であると仮定します。

4

3 に答える 3

4

これは、既存のアイテムをフェッチするかGetOrAdd、指定されたキーのエントリがない場合は新しいアイテムを追加するように明示的に設計されています。

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

質問のコメントに記載されているように、これはそれItemCollectionがスレッドセーフであることを前提としています。

于 2014-06-12T13:22:22.273 に答える
1

GetOrAddメソッドを使用する必要があります。

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

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

ItemCollection collection = result.GetOrAdd(someKey, _ => new ItemCollection());
collection.Add(newItem);
于 2014-06-12T13:23:29.527 に答える
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(...);
于 2014-06-12T13:23:50.897 に答える