今回はC#の非同期処理を理解するためにawaitとasyncについて勉強していきます。
asyncとawaitとは
asyncとawaitとはC#5.0以降から追加された機能です。
asyncとawaitを使うことで実装が面倒な非同期処理をシングルスレッドを書くかのような感じで実装することができます。
awaitとは文字通り待機するという意味です。
awaitを付けた場合その処理は一度別スレッドで実行されますが、その処理が終了するまでメインスレッドも待機したまま処理が進みません。
asyncはawaitを使用する際にメソッドにつけるおまじないのようなものです。
asyncとawaitを使ったメソッドは以下のようなものになります。
static async Task Main()
{
await TaskA();
}
awaitを使って非同期処理が終わるまで待機する
それではawaitを使って非同期処理が終了するまでメインスレッドが待機する処理を実装してみます。
using System;
using System.Threading.Tasks;
class AsyncSample
{
static async Task Main()
{
Console.WriteLine("Start");
await AsyncProcess();
Console.WriteLine("End");
}
private static async Task AsyncProcess()
{
await Task.Run(() =>
{
for (int i = 0; i < 1000; ++i)
{
Console.WriteLine(i);
}
});
}
}
実行結果は以下の通りです。
Start
0
1
2
3
~
999
End
実行結果から見て分かる通りAcyncProcessメソッドの処理が終了するまでMainメソッドの処理が進んでいませんね。
非同期処理を待たない
先ほどはawaitを使って非同期処理が終わるまで待機しましたが時と場合によっては、せっかく非同期処理をしているので処理が終わるのをまたずにメインスレッドを進めたい場合もあります。
そういうときはawaitを付けなければいいだけです。
先ほどのサンプルからMainメソッドを以下のように変更してみます。
static async Task Main()
{
Console.WriteLine("Start");
AsyncProcess();
Console.WriteLine("End");
}
実行結果は以下の通りです。
Start
0
1
2
3
~
18
End
AcyncProcessメソッドの処理が終了するのを待たずにMainメソッドの処理が進んでいますね。
awaitを使わない場合、デッドロックにならないように注意する必要があります。
複数のスレッドで同じ変数を変更したり、参照していたりするとデッドロックが起きる可能性がありますので注意しましょう。
まとめ
今回はawaitとasyncの基本的な使用方法について学んでいきました。
awaitとasyncのおかげでC#は手軽に非同期処理が実装できるので楽ですね。
asyncを付けたメソッドから戻り値を受け取る方法について調べました。