タスクは、生成の開始からタスクスケジューラーへの登録、タスクの実行、完了など、自身のライフサイクルが現在どのような状態にあるかを事細かに把握しています。また、タスクインスタンス毎に割り当てられる一意のIDも保持しています。今回は、これらタスクの内部状態について見ていきます。
タスクのライフサイクル
タスクのライフサイクルは、Taskクラスの読み取り専用プロパティであるStatusプロパティに問い合わせることで取得できます。取得できるTaskStatus列挙体は次のようになっています。
値 | 説明 |
---|---|
Created | タスクは明示的に生成されましたが、まだスケジューラーへの登録はされていません。(= Startメソッドは呼び出されていません) |
WaitingForActivation | タスクはContinueWith、ContinueWhenAll、FromAsyncメソッドなどにより暗黙的に生成され、すでに実行をスケジューリングされています。 |
WaitingToRun | タスクはスケジューリングされていますが、まだ実行されていません。 |
Running | タスクは現在実行中です。 |
WaitingForChildrenToComplete | タスクの完了していますが関連付けられている子タスクが完了していないため、その完了を待機しています。 |
RanToCompletion | タスクは正常に完了しました。 |
Canceled | タスクはスケジューラーによって実行を取り消されたか、実行中にキャンセルされました。 |
Faulted | タスクはハンドルされない例外が発生したため異常終了しました。 |
タスクの最終状態としては、RanToCompletion、Canceled、Faultedのいずれかになります。利用可能性の高いこれらの値をより便利に利用できるよう、TaskクラスにIsCompleted、IsCanceled、IsFaultedプロパティが提供されています。IsCompletedはStatusプロパティがRanToCompletion、Canceled、Faultedのいずれかのときにtrueを返すので注意が必要です。また、IsFaultedプロパティがtrueの場合はTask.Exceptionプロパティはnull以外を返します。
以前、タスクの継続で紹介した、「成功時のみ継続、キャンセル時のみ継続、エラー時のみ継続」は、これらの最終状態に依存していたことが理解できたかと思います。
タスクIDとVisual Studioのデバッガー
各タスクインスタンスには自身を表す一意のIDが割り振られます。このタスクIDは、読み取り専用のTask.Idプロパティで取得することができます。タスクIDはインスタンス生成時に0に初期化され、初めてIdプロパティを呼び出したときに一意なIDが割り当てられます。タスクIDは1から始まり、IDが割り振られるごとに1ずつインクリメントされていきます。また、コード上でIdプロパティを呼び出していなくても、Visual Studioのデバッガー上でタスクIDが表示されるだけでも割り当てられます。以下にVisual Studioのデバッガー画面を示します。
上図ではタスクが2つあり、それぞれIDに1、2が割り振られています。また、ID = 2のタスクは実行中ですが、ID = 1のタスクはスケジューリングされているものの実行されておらず、実行を待機していることも分かります。その他、Visual Studioのデバッガーではタスクをより視覚的に解析することも可能になっています。(下図参照)
次回予告
今回はタスクの内部状態について触れました。ライフサイクルなどについて知ることで、タスクがどのように動作しているかをより理解できたかと思います。最終回となる次回は、タスク上でUIコンポーネントを操作する方法について見ていきたいと思います。