「C Sharpの基礎 - マルチスレッドとGUI」の版間の差分

ナビゲーションに移動 検索に移動
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>

案内メニュー