ニートが学ぶ非同期処理 その2

はいどーもこんにちはニートです。
今回もスレッドをホニャララしていきたいと思います。

スレッドから戻り値を得る

別スレッドで実行した結果出力された戻り値をメインスレッドで受け取りたいというシチュエーションは多いと思います。
前回の記事ではThreadやThreadPoolをそのまま使う例や、delegateを使って別スレッドを開始しましたが、これらの方法を使って戻り値を得るのは結構面倒です。
また、これらを現在そのまま使うことってあんまりないんじゃないかなとも思っています。
というわけでとりあえずBackgroundWorkerの例から。

workArgs.Resultに結果の値を設定しています。
これをRunWorkerCompletedイベントハンドラに登録するメソッドの中でなんぞ使えば、非同期に実行した結果を使って色々とできるわけですね。
ぶっちゃけ不便な感じがします。

ちゅーわけでやはりTaskです。
とりあえずコードをドン。

BackgroundWorkerを使ったものよりも、だいぶん直感的なコードになっています。
普通にタスクを作成したあと、別スレッドでタスクを開始します。
task.ResultはResultプロパティを参照した時点でスレッドの処理が完了していない場合、完了するまでブロックするようです。
なので結果は

1.タスク開始
2.タスク終了
3.メインスレッドで結果を~
4.全て終了

となります。

スレッドの処理完了後に別の処理を続けて実行する

一つの処理が完了したら、続けて別の処理をおこないたい、ということはよくあると思います。
BackgroundWorkerを使う場合はRunWorkerCompletedイベントに登録したイベントハンドラを利用して後続の処理を書いていけばよいと思います。
また、前項で示したように処理の結果はworkArgs.Resultに入っているので、何かしらの戻り値を利用して処理を続けていく場合はこれを利用すればよいみたいです。

ではタスクを使うとどうなるのでしょうか。
こんな感じで書けるようです。

正直、煩雑さは否めませんね。
もう少し簡潔に書く方法も用意されているみたいですが(メソッドチェーンやら何やら使って)、この辺からasync/awaitを使いたくなってきます。

async/awaitでタスクの完了を待つ

ちゅーわけでasync/awaitを使って先ほどのコードを書き直したいと思います。

もうちょっといい書き方がありそうな気がしますが(あとvoid使うなとか色々あるみたいです)、とりあえずこれでも同じ結果が得られます。
awaitが処理を待っている&戻り値を返している感じですね。
最初に書いた例よりは直感的じゃないかなーと思います。
Taskおよびasync/awaitは引き続き勉強していきますよ。

終わりに

非同期処理が理解できれば色々と便利そうなので、この調子でガンガン進めていこうと思います。
ほなそんな感じでまた。

フォローする