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

はいどーもこんばんは、もう挨拶が思い浮かびません。
今回はasync/awaitの動きを追っていきたいと思います。

とりあえず動かしてみる

awaitの挙動を確認するため、とりあえず以下のコードを用意してみました。

これを実行すると僕の環境では例えばこんな結果になりました。

見るとDoTask1が完全に終了してから別スレッドが立ち上がり(Mainメソッドで一回目のConsole.WriteLineが実行されている)、それから「最初のタスク開始」という文字が表示されています。
「計算結果」という出力のあとにもメインスレッドでは相変わらずConsole.WriteLineが実行されており、「DoTask2終了」という文字が表示される前に「5」という文字列が出力されています。
これはまさに非同期に実行されているために起こることです。

終了を待ちたい

DoTask2の中でも使われている「await」を使うと、そのスレッドの処理(正確には非同期の処理?)が終了するのを待つことができます。
なのでもしDoTask1はDoTask2の終了を待ってから「DoTask1終了」と表示したいとすれば、DoTask1中のDoTask2();の前にawaitをつければいいことになります。
僕の環境での結果は例えば以下のようになりました。

値も返したい

スレッドの終了を待つだけでなく、Taskで値を返したい場合もあると思います。
例えばDoTask2の計算結果をDoTask1に返して、何やら利用したいとします。
例えばこんな風に書けます。

DoTask2の戻り値がTask型からTask型になっています。
しかしreturnしている値はただのint型です。
次にDoTask1を見てください。
DoTask2の結果をawaitしています。
awaitすると、DoTask2が終了したときそのままint型の結果を返してもらえるようになります。
結果はこんな感じ。

もしもDoTask1でawaitせず、TaskのResultをそのまま受け取ったらどうなるのでしょうか?
例えばこんな感じに。

この場合は同期的に処理されるため、MainメソッドはDoTask1の処理が完了するのを待ちます(result.Resultで止められている)。
つまりDoTask2が完全に終了してかつ「DoTask1終了」と表示してからようやく「123456…」という文字列の出力が始まります。

ちなみにですが、result.Resultがなければ、結果は想定していたものと全然違うものになります(ブロックするものが何もないので、DoTask2を起動しつつそのままDoTask1が終了して、Mainスレッドの内容も実行される)。

ウーン、ややこしくなってきました。

終わりに

だんだん複雑になってきましたが、気にせずガンガン進めますよ。
非同期マスターしてぼかぁUniRxおよびサーバーサイド技術と仲良しこよしするんや。

ほなそんな感じでまた。

フォローする