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

103行目: 103行目:


== ConfigureAwait(false) ==
== ConfigureAwait(false) ==
TaskのWaitメソッドやResultは、デフォルトで元のスレッドへ戻ろうとする。<br>
GUIアプリケーションでは、以下のように記述すると、簡単にデッドロックが発生する。<br>
そのため、GUIアプリケーションでは、下記のように記述すると簡単にデッドロックが発生する。<br>
なぜなら、TaskのWaitメソッドやResultは、元のスレッドへ戻ろうとするからである。<br>
<br>
以下の場合、methodAsync().Wait()を呼んだ時点で親スレッドがスリープする。<br>
なぜなら、methodAsync()の終了後に親スレッドに戻ろうとするが、既に親スレッドがスリープしているため、<br>
処理を続けることができないからである。<br>
その結果、親スレッドは子スレッドを待ち続け、子スレッドは親スレッドに戻ろうとして、デッドロックが発生する。<br>
  <source lang="c#">
  <source lang="c#">
  // デッドロックが起きるサンプルコード(GUIアプリケーションのみ)
  // デッドロックが起きるサンプルコード(GUIアプリケーションのみ)
// コンソールアプリケーションでは正常に動作する
  public void callMethod()
  public void callMethod()
  {
  {
117行目: 123行目:
  }
  }
  </source>
  </source>
<br>
上記の場合、methodAsync().Wait()を呼んだ時点で親スレッドがスリープする。<br>
次に、methodAsync()が終了後、親スレッドに戻ろうとするが、既に親スレッドがスリープしているため処理を続けることができない。<br>
その結果、親スレッドは子スレッドを待ち続け、子スレッドは親スレッドに戻ろうとして、デッドロックが発生する。<br>
<br>
<br>
対策として、以下のように記述するとデッドロックが回避できる。(戻るスレッドはどこでもよい場合)<br>
対策として、以下のように記述するとデッドロックが回避できる。(戻るスレッドはどこでもよい場合)<br>
  <source lang="c#">
  <source lang="c#">
  // デッドロックが起きないサンプルコード
  // デッドロックが起きないサンプルコード(GUIアプリケーションのみ)
  public void callMethod()
  public void callMethod()
  {
  {
130行目: 132行目:
  }
  }
   
   
  public async Task waitAsync()
  public async Task methodAsync()
  {
  {
     return await Task.Delay(1000).ConfigureAwait(false);
     return await Task.Delay(1000).ConfigureAwait(false);