同時実行するときのコレクション
以下を実行すると、ArgumentException になったり result が歯抜けになったりする。
var result = new Dictionary<int, int>(); Parallel.For(0, 10000, i => { result.Add(i, CalculateSomething(i);); });
これは Dictionary
がスレッドセーフでないため。 ConcurrentDictionary
を使おう。
var result = new ConcurrentDictionary<int, int>(); Parallel.For(0, 10000, i => { result.Add(i, CalculateSomething(i);); });
List
であれば ConcurrentBag
になる。 Visual Studio のサジェストから CuncurrentList
的なものを必死で探しても見つからないので注意。
var result = new ConcurrentBag<int>(); Parallel.For(0, 10000, i => { result.Add(CalculateSomething(i);); });
同時実行時の実行結果がコレクションのコレクションとして格納したい場合があるが ConcurrentBag
には AddRange
が無い。拡張メソッドを書いてやる。
public static void AddRange<T>(this ConcurrentBag<T> @this, IEnumerable<T> collection) { foreach (var element in collection) { @this.Add(element); } }
これを使ってこう。
var result = new ConcurrentBag<IEnumerable<int>>(); Parallel.For(0, 10000, i => { result.AddRange(GetNumbers(i);); });