TAP による非同期コードの基本的な書き方
「async と await の基本的な使い方」では、.NET Framework の WebClient クラスの DownloadStringTaskAsync メソッドの利用方法を通して、非同期メソッドの呼び出し方、処理の待ち方、 そして結果の受け取り方をみました。
C# 5.0 の非同期プログラミングでは async、await および Task を利用することによって、 非同期メソッドが非常に簡単に利用できることがわかったとおもいます。
ここでは、自前で非同期メソッドを実装する場合に、どのように書くのかを確認します。
Run.Task を利用して非同期処理を記述する
ここでは例として、時間のかかる処理を 5 秒間 (5000ms) のスリープとします。
次のようなテスト用アプリケーションを作りました。
上側のボタンで戻り値がない場合のコードを、下側のボタンで戻り値がある場合のコードを試します。
戻り値がない場合
5秒かかる処理を行うメソッド側、その呼び出し側は次のように書きます。
Async メソッドで Task を返している点、その中で Task.Run で処理を実行しているところがポイントです。
動作確認として、次のようにデバッグトレースを書いてみると、実際にどこで処理待ちになったかわかります。
この実行結果は次の通りでした。
--- Begin ---
System.Threading.Tasks.Task
--- End ---
--- Await Begin ---
*** Delay Begin ***
ここで5秒待ち....
*** Delay End ***
--- Await End ---
戻り値を受け取る場合
次は時間のかかる処理を行った結果、呼び出し側でその結果を受け取りたい場合 (ここでは int の 123) に、 どのように記述するかみてみましょう。
その場合は Task<int> を返すメソッドを記述します。
こちらもデバッグトレースを埋め込んで、実行の様子を見てみましょう。
この実行結果は次の通りでした。
--- Begin ---
System.Threading.Tasks.Task`1[System.Int32]
--- End ---
--- Await Begin ---
*** Delay Begin ***
ここで5秒待ち....
*** Delay End ***
r = 123
--- Await End ---
また、イベントハンドラがブロックされていないことを確認するために、 await して受け取った戻り値をポップアップで表示します。
これを実行してボタンを連打します。(連打できている時点でイベントハンドラが返っているのですが・・・)
すると、5秒を過ぎた頃から次のようにポップアップが多数表示されました。
長時間かかる処理を実行しなければならない場合に、これまではバックグラウンドワーカーを使うなど、 少々面倒な書き方をする必要がありましたが、これで簡単に処理が記述できるようになりましたね。