【C#】awaitとは? 150文字以内で説明してみた

スポンサーリンク

awaitとは?

awaitとは、「待機する」ために使う予約語である。
awaitをつけて関数を呼ぶと、その関数が終了するまで、そこで処理が止まる。
(処理が止まっている間は、別のイベントなどを処理することができる)
awaitのついた関数が終了すると、止まっていた処理が続きから再開される。

以上


以下、awaitの周辺知識

なぜawaitをつけなければいけないのか?

awaitをつけて呼び出している関数は、実は非同期な関数である。

非同期な関数の処理結果を使って、今の処理をしたいとする。
そのためには、非同期な関数の処理が終わるまで待つ必要がある
だから、awaitをつけて処理が終了するのを待っているのだ。

例、非同期な関数funcAsync()の戻り値を使用する。

async void main() {
    var result = await funcAsync();  //funcAsync()の終了まで待機する
    Console.WriteLine(result);      
}
同期、非同期とは?

プログラミングにおける同期とは、処理の実行タイミングがそろっているいること(順番に実行されるなど)を指す。

例えば、普通のプログラムは、同期である。上から順番に処理が実行される。各行ばらばらに実行されるなんてことはない。

一方、非同期とは、(ある対象に対して)処理の実行タイミングがそろっていないこと(各々勝手に処理を進めていて、処理順序がどのようになるかわからないなど)を指す。

例えば、YouTube流しながらゲームする、など。YouTubeの状態に関係なくゲームは動作する(逆も然り)ので、YouTubeのプログラムとゲームのプログラムは非同期である。

awaitの目的

非同期とか、タスクとか、スレッドとか、難しいよね。
そんなん考えずにプログラミングしたいよね。
そんな仕組み作ってみました、はいどーん、await使ってね。ってかんじ。

awaitを使えば、非同期な関数使っても、簡単に同期的に書けるよ。ってこと。

例えば以下のソースでは、非同期な処理(funcAsync)を行っているにも関わらず、awaitを使っているだけで、普段と変わらない同期的なソースコードになっている。

async void main(){
    var result = await funcAsync();
    Console.WriteLine(result);
}

asyncとは?

「この関数は非同期です」という宣言。
awaitを使うためには、関数にasyncをつけなければならない

このため、検索するとawaitとasyncが同時ヒットすることが多い。

非同期処理のソースコード

非同期処理の関数というのは、たいていはライブラリで提供されている
そのため自分でわざわざ作成しなくても、awaitをつけるだけで簡単に利用できる
だが、ときには自分で非同期な処理を作成しなければいけないときもあるだろう。
というわけで、今まで隠蔽してきた非同期関数funcAsync()の中身の例を、記載しておく。

//非同期関数の例。
Task<string> funcAsync(){
    return Task.Run(() => {
        //...スレッドプールで実行したい処理を記載
        return "HelloWorld";
    });
}
async void 使用例1(){
  string str = await funcAsync();
  Console.WriteLine(str);  //HelloWorld
}

//ちなみに、今まで関数に限定してawaitを説明してきたが、
//正しくはTaskに対してawaitを使う
async void 使用例2(){
    Task<string> task = funcAsync();
    string str = await task;  //awaitを使用した場所で待機する。Task<string>からstringを取り出す
    Console.WriteLine(str);   //HelloWorld
}

ここまで覗くと、いままで省いてきた、Task<T>とか、Task.Run()とか、スレッドとか、なんかめんどくさそうな単語がたくさん出てくる。

詳しい説明はここでは行わないが、簡単な説明や、上手く説明されている別サイトへのリンクを残しておく。

Task.Run()とは?

引数1:関数
戻り値:Task<T>
処理概要
渡した関数を別スレッド(スレッドプール)で処理してくれる。

コード例

Task.Run(() => { /* スレッドプールで実行したい処理を記載 */ });
「() => {}」の文法がわからない人は、「ラムダ式」で検索
スレッドとは?、スレッドプールとは?

以下のサイトがいい記事だと感じた。

スレッドプールとタスク

おわりに、この記事を書いた経緯

私はawaitが知りたかったのに、スレッドとか、非同期とか、タスクとかの説明ばっか検索にヒットするから、そんなんすっとばしてawaitをまず説明してみた。

 

コメント

タイトルとURLをコピーしました