12,992
回編集
99行目: | 99行目: | ||
<br><br> | <br><br> | ||
== | == マルチスレッドのキャンセル処理 == | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
private void btnStart_Click(object sender, RoutedEventArgs e) | private void btnStart_Click(object sender, RoutedEventArgs e) | ||
169行目: | 169行目: | ||
{ | { | ||
source.Cancel(); | source.Cancel(); | ||
} | |||
</syntaxhighlight> | |||
<br> | |||
以下の例では、DoWorkメソッドの引数に<code>CancellationToken</code>構造体を指定して、<br> | |||
メソッド内で<code>IsCancellationRequested</code>プロパティまたは<code>ThrowIfCancellationRequested</code>メソッドを使用して、キャンセル処理をしている。<br> | |||
<br> | |||
<u><code>ThrowIfCancellationRequested</code>メソッドを使用してキャンセルする場合、非同期メソッドの<code>Task</code>の状態が<code>Canceled</code>の状態になるため、キャンセルされたということが明確になる。(推奨)</u><br> | |||
<br> | |||
<code>await</code>処理のメソッド内でキャンセルする場合、<code>await</code>処理のメソッド内にも再帰的に<code>CancellationToken</code>構造体を渡す。<br> | |||
各非同期メソッドに渡す<code>CancellationToken</code>構造体は、基本的に<code>CancellationTokenSource</code>クラスから生成する。<br> | |||
<code>CancellationTokenSource</code>クラスの<code>Cancel</code>メソッドを呼ぶことにより、<code>CancellationToken</code>オブジェクトが<code>Canceled</code>の状態になる。<br> | |||
<br> | |||
一般的な非同期ライブラリのAPIであれば、時間を要する可能性がある処理には<code>CancellationToken</code>構造体を受け入れるオーバーロードが存在する。<br> | |||
<syntaxhighlight lang="c#"> | |||
private CancellationTokenSource cts = null; | |||
private async void button_Click(object sender, EventArgs e) | |||
{ | |||
cts = new CancellationTokenSource(); // CancellationTokenSourceクラスのインスタンスを生成 | |||
int intValue = await DoWork(this.cts.Token); // CancellationTokenSourceオブジェクトからCancellationTokenを取り出して渡す | |||
} | |||
private async Task<int> DoWork(CancellationToken token) | |||
{ | |||
await DoHeavyWork(token); // 時間の掛かる処理にもCancellationToken構造体を渡す | |||
// キャンセル処理 (IsCancellationRequestedプロパティを使用する場合) | |||
if (token.IsCancellationRequested) | |||
{ | |||
return 1; | |||
} | |||
// キャンセル処理 (ThrowIfCancellationRequestedメソッドを使用する場合) | |||
// これは、キャンセルが要求されている場合、例外OperationCanceledExceptionを発生させる | |||
//token.ThrowIfCancellationRequested(); | |||
return 0; | |||
} | |||
// キャンセルボタン押下 | |||
private void btnCancel_Click(object sender, RoutedEventArgs e) | |||
{ | |||
this.cts.Cancel(); // Cancelメソッドを実行した時、非同期メソッドであるDoWorkメソッドがキャンセルされる | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |