タスクを実行した際、途中でキャンセルしたいことがあります。その際の方法を記載します。
Taskクラス によるタスクキャンセルは、CancellationTokenSourceクラスを使用します。
タスクキャンセル要求は、CancellationTokenSource.Cancel()メソッドを実行します。
これによりキャンセルフラグが立ち、このフラグを参照することによりキャンセル処理を実行します。
ThrowIfCancellationRequested()によるキャンセル方法
オペレーション側プログラム
Dim cts As CancellationTokenSource
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
cts = New CancellationTokenSource()
Try
Dim t = ActionAsync(cts.Token) 'タスクの実行
Await t '非同期的に完了待ち
Catch ex As OperationCanceledException
MessageBox.Show("キャンセルされました")
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
cts.Cancel() 'タスクのキャンセル要求
End Sub
タスク側プログラム(ThrowIfCancellationRequestedメソッド抜け出し)
Async Function ActionAsync(token As CancellationToken) As Task(Of Boolean)
Dim result As Boolean = Await Task.Run(
Function() As Boolean
For i As Integer = 0 To 100
token.ThrowIfCancellationRequested() 'キャンセル時の処理
Thread.Sleep(1000)
Next
Return True
End Function
)
MessageBox.Show("タスク終了")
Return result
End Function
CancellationToken構造体のThrowIfCancellationRequested()メソッドで、キャンセルフラグをチェックします。
また、実際のキャンセルフラグは、CancellationToken.IsCancellationRequestedプロパティに設定されていて
このフラグが立ったらタスク側は、OperationCanceledException例外をスローするように作成します。
キャンセルフラグの例外スローのコードは、以下のコードのようになります。
If (token.IsCancellationRequested) Then
Throw New OperationCanceledException(token)
End If
上記を一文で書けるようにメソッドが用意されています。
token.ThrowIfCancellationRequested()
例外のスローではない IsCancellationRequestedでのキャンセル抜け出し
ThrowIfCancellationRequested()での抜け出しは、 例外スローするので、上に記載したコードではキャンセルの際、MessageBox.Show(“タスク終了”)実行されません。
そこで、IsCancellationRequestedを参照して抜け出すようにします。
タスク側プログラム(IsCancellationRequestedプロパティ抜け出し)
Async Function ActionAsync(token As CancellationToken) As Task(Of Task)
Dim result As Task = Task.Run(
Sub()
While True
If (token.IsCancellationRequested) Then 'キャンセル時の処理
Exit While
End If
Thread.Sleep(1000)
End While
End Sub
)
Await result
MessageBox.Show("タスク終了")
Return result
End Function