anatsuk1のウェブログ

ブログを書いてみたい!

C# Taskクラスとawait演算子/asyncキーワード

目的

C#での非同期メソッドについて調べた結果をメモしておく


Taskクラス

Taskのインスタンスを直接作成することは多くなく、ライブラリが提供する非同期メソッドの戻り値として取得することが多い。

例)
Task getStringTask = client.GetStringAsync("https://docs.microsoft.com");

しかしながら、Taskクラスは以下の操作でインスタンスを作成することができる。
  • Task.Run
  • new Task
  • TaskFactory.StartNew
これらを使用するときは自身で非同期処理を実装したいときだろう。

例)
Task t = Task.Run( () => { Console.WriteLine("Hello."); });
https://docs.microsoft.com/ja-jp/dotnet/api/system.threading.tasks.task


await演算子

awaitのオペランドとしてTaskインスタンスを指定することができる。
効果としては以下の二つをあげることができる。

  • メソッドの実行は中断され、コントロールは呼び出し元へ戻る
  • Taskインスタンスが完了すると、メソッドの実行が再開される。
ここでコントロールが呼び出し元に戻ることに注意すること。
具体的には、呼び出し元がawait呼び出しでない場合、呼び出し元では待機できない。
これはイベントハンドラ一般に当てはまる。

特に注意すべき点として、Windowで発生するClosed、Closingイベントは呼び出し元へ戻るとそのままWindowが閉じられ、メソッドの処理が再開されることはないので注意すること。
上記イベントの場合は、TaskインスタンスのWait()系のメソッドを呼び出しコントロールを呼び出し元に戻さないようにする必要がある。

await演算子に指定するTaskインスタンスはConfigureAwait(false)を呼び出して取得したTaskインスタンスを指定することが望ましい。
ただし、再開される処理がUIスレッドを前提とする場合は、上記は当てはまらない。
ConfigureAwait(false)の場合には、UIスレッドが実行コンテキストとして選ばれることはないため。


ayncキーワード

awaitを演算子として使用するメソッドでは指定する必要がある。