今回も、CountdownEventクラスについて。
CountdownEventクラスは、.NET 4.0からSystem.Threading名前空間に追加されたクラスです。
今回は、キャンセルトークン (CancellationToken)を利用した待機のキャンセルについてです。
やり方は、ManualResetEventSlimクラスの場合は同じです。
CancellationTokenは、.NET 4.0から追加されたキャンセル処理のための新たな仕組みです。
タスク並列ライブラリ (TPL) でよく利用されます。
キャンセルトークンを指定するWaitメソッドの場合、通常のシグナル状態になるまで待機すると同時に
キャンセルされたか否かも検知するようになります。
注意点として、キャンセルトークンを指定した場合、キャンセル操作が行われると
OperationCanceledExceptionが発生するので、try-catchが必須となります。
以下、サンプルです。
#region CountdownEventSamples-03 /// <summary> /// CountdownEventクラスについてのサンプルです。(3) /// </summary> /// <remarks> /// CountdownEventクラスは、.NET 4.0から追加されたクラスです。 /// JavaのCountDownLatchクラスと同じ機能を持っています。 /// </remarks> public class CountdownEventSamples03 : IExecutable { public void Execute() { // // CountdownEventには、CancellationTokenを受け付けるWaitメソッドが存在する. // 使い方は、ManualResetEventSlimクラスの場合と同じ。 // // 参考リソース: // .NET クラスライブラリ探訪-042 (System.Threading.ManualResetEventSlim) // http://d.hatena.ne.jp/gsf_zero1/20110323/p1 // CancellationTokenSource tokenSource = new CancellationTokenSource(); CancellationToken token = tokenSource.Token; using (CountdownEvent cde = new CountdownEvent(1)) { // 初期の状態を表示. Console.WriteLine("InitialCount={0}", cde.InitialCount); Console.WriteLine("CurrentCount={0}", cde.CurrentCount); Console.WriteLine("IsSet={0}", cde.IsSet); Task t = Task.Factory.StartNew(() => { Thread.Sleep(TimeSpan.FromSeconds(2)); token.ThrowIfCancellationRequested(); cde.Signal(); }, token); // // 処理をキャンセル. // tokenSource.Cancel(); try { cde.Wait(token); } catch (OperationCanceledException cancelEx) { if (token == cancelEx.CancellationToken) { Console.WriteLine("***CountdownEvent.Wait()がキャンセルされました***"); } } try { t.Wait(); } catch (AggregateException aggEx) { aggEx.Handle(ex => { if (ex is OperationCanceledException) { OperationCanceledException cancelEx = ex as OperationCanceledException; if (token == cancelEx.CancellationToken) { Console.WriteLine("***タスクがキャンセルされました***"); return true; } } return false; }); } // 現在の状態を表示. Console.WriteLine("InitialCount={0}", cde.InitialCount); Console.WriteLine("CurrentCount={0}", cde.CurrentCount); Console.WriteLine("IsSet={0}", cde.IsSet); } } } #endregion
実行結果は以下のようになります。
InitialCount=1 CurrentCount=1 IsSet=False ***CountdownEvent.Wait()がキャンセルされました*** ***タスクがキャンセルされました*** InitialCount=1 CurrentCount=1 IsSet=False
待機をキャンセルしたので、CurrentCountとIsSetの値が変更されていないことが分かります。
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場