.NET Framework 4 になり Task Parallel Library (TPL) が追加され,並列処理が容易に行えるようになりました。
並列プログラミングでよく用いられるパターンに producer-consumer パターンがあります。 TPL を用いた producer-consumer の例を紹介します。
var random = new Random(); var queue = new ConcurrentQueue<Person>(); bool closed = false; int proceeds = 0; Action producer = () => { do { int money; lock (random) { money = random.Next(1000, 10000); if (random.NextDouble() > 0.99) { closed = true; } } Person customer = new Person() { PocketMoney = money }; queue.Enqueue(customer); } while (!closed); }; Action consumer = () => { Person customer; while (!closed || !queue.IsEmpty) { if (queue.TryDequeue(out customer)) { int take; lock (random) { take = random.Next(customer.PocketMoney); } Interlocked.Add(ref proceeds, take); } } }; Parallel.Invoke(producer, consumer, consumer); Console.WriteLine("売上金: {0:#,0}円", proceeds); class Person { public int PocketMoney { get; set; } }
producer
は顧客が待ち行列を作って店に並ぶイメージです。 consumer
は顧客に応対してポケットマネーを頂戴します。最終的に consumer
が稼いだ金額の合計をコンソールに出力します。ここでは 1-producer-N-consumer の例を示していますが,もちろん 1-1 や N-N に対応することも容易です。
この例では ConcurrentQueue
クラスを用いていますが,他にもいくつかのスレッドセーフなコレクションが System.Collections.Concurrent
名前空間に定義されています。個人的な感想としては,順序を規定しないコレクションである ConcurrentBag
クラスが用意されているのが使いやすくて良いと思います。