.NET Framework 4 になり Task Parallel Library (TPL) が追加され,並列処理が容易に行えるようになりました。
並列プログラミングでよく用いられるパターンに producer-consumer パターンがあります。 TPL を用いた producer-consumer の例を紹介します。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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
クラスが用意されているのが使いやすくて良いと思います。