今回も、CountdownEventクラスについて。
CountdownEventクラスは、.NET 4.0からSystem.Threading名前空間に追加されたクラスです。
今回は、N個の処理が存在している状態で、ある規定数分が終了したら
メインスレッドの待機を解除して、先に進むサンプルです。
CountdownEventがよく利用されるパターンだと思います。
何個完了したら待機を解除するかの数を、処理数分にしたら
全処理が完了した後に待機を解除することになります。
以下、サンプルです。
#region CountdownEventSamples-02 /// <summary> /// CountdownEventクラスについてのサンプルです。(2) /// </summary> /// <remarks> /// CountdownEventクラスは、.NET 4.0から追加されたクラスです。 /// JavaのCountDownLatchクラスと同じ機能を持っています。 /// </remarks> public class CountdownEventSamples02 : IExecutable { public void Execute() { const int LEAST_TASK_FINISH_COUNT = 3; // // 複数のスレッドから一つのCountdownEventをシグナルする. // // CountdownEventがよく利用されるパターンとなる。 // N個の処理が規定数終了するまで、メインスレッドの続行を待機するイメージ. // // 以下の処理では、5つタスクを作成して、3つ終わった時点で // メインスレッドは処理を続行するようにする. // // N個の処理が全部終了するまで、メインスレッドの続行を待機する場合は // CountdownEventのカウントをタスクの処理数と同じにすれば良い。 // using (CountdownEvent cde = new CountdownEvent(LEAST_TASK_FINISH_COUNT)) { // 初期の状態を表示. Console.WriteLine("InitialCount={0}", cde.InitialCount); Console.WriteLine("CurrentCount={0}", cde.CurrentCount); Console.WriteLine("IsSet={0}", cde.IsSet); Task[] tasks = new Task[] { Task.Factory.StartNew(TaskProc, cde), Task.Factory.StartNew(TaskProc, cde), Task.Factory.StartNew(TaskProc, cde), Task.Factory.StartNew(TaskProc, cde), Task.Factory.StartNew(TaskProc, cde) }; // // 3つ終わるまで待機. // cde.Wait(); Console.WriteLine("5つのタスクの内、3つ終了"); Console.WriteLine("メインスレッド 続行開始・・・"); Thread.Sleep(TimeSpan.FromSeconds(1)); // // 残りのタスクを待機. // Task.WaitAll(tasks); Console.WriteLine("全てのタスク終了"); // 現在の状態を表示. Console.WriteLine("InitialCount={0}", cde.InitialCount); Console.WriteLine("CurrentCount={0}", cde.CurrentCount); Console.WriteLine("IsSet={0}", cde.IsSet); } } void TaskProc(object data) { Console.WriteLine("Task ID={0} 開始", Task.CurrentId); Thread.Sleep(TimeSpan.FromSeconds(new Random().Next(10))); // // 既に3つ終了しているか否かを確認し、まだならシグナル. // CountdownEvent cde = data as CountdownEvent; if (!cde.IsSet) { cde.Signal(); Console.WriteLine("***カウントをデクリメント*** Task ID={0} CountdownEvent.CurrentCount={1}", Task.CurrentId, cde.CurrentCount); } Console.WriteLine("Task ID={0} 終了", Task.CurrentId); } } #endregion
実行結果は以下のようになります。
InitialCount=3 CurrentCount=3 IsSet=False Task ID=1 開始 Task ID=2 開始 Task ID=3 開始 Task ID=4 開始 ***カウントをデクリメント*** Task ID=4 CountdownEvent.CurrentCount=2 Task ID=4 終了 Task ID=5 開始 ***カウントをデクリメント*** Task ID=5 CountdownEvent.CurrentCount=1 Task ID=5 終了 ***カウントをデクリメント*** Task ID=3 CountdownEvent.CurrentCount=0 Task ID=3 終了 5つのタスクの内、3つ終了 メインスレッド 続行開始・・・ Task ID=2 終了 Task ID=1 終了 全てのタスク終了 InitialCount=3 CurrentCount=0 IsSet=True
指定した数分終了した後、メインスレッド側の待機が解除されているのが分かります。
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場