asyncは、一般のメソッド以外に、匿名メソッドやラムダ式に付ける場合もある。
async - C# リファレンス | Microsoft Docs
非同期メソッドの構文(2/3) - @IT
awaitを扱った時の最後のコードを見てみる。
// 名前空間の登録 using System; // 共通データ型と基本クラス(System名前空間) using System.Threading; // マルチスレッド(System.Threading名前空間) using System.Threading.Tasks; // タスク(System.Threading.Tasks名前空間) // MainClassの定義 class MainClass { // Mainの定義 static void Main() { // 実行前 Console.WriteLine("Main Begin"); // "Main Begin"と出力. // SimpleMethodを実行. SimpleMethod(); // SimpleMethodを呼ぶ. // SimpleMethodを抜けた後.(awaitで抜けた直後にここは実行される.) Console.WriteLine("SimpleMethod After"); // "SimpleMethod After"と出力. // 10秒待つ. Thread.Sleep(10000); // 10000ミリ秒休止. // 実行後 Console.WriteLine("Main End"); // "Main End"と出力. } // SimpleMethodの定義 static async void SimpleMethod() // awaitのあるメソッドにはasyncを付けないといけない. { // 実行前 Console.WriteLine("SimpleMethod Begin"); // "SimpleMethod Begin"と出力. // Task.Runで指定のActionを実行. await Task.Run(() => // awaitでこの処理を待つ. { // LongProcMethod実行前 Console.WriteLine("LongProcMethod Before"); // "LongProcMethod Before"と出力. // LongProcMethodを実行. LongProcMethod(); // LongProcMethodを呼ぶ. // LongProcMethod実行前 Console.WriteLine("LongProcMethod After"); // "LongProcMethod After"と出力. }); // 実行後(上のawaitの付いたタスクが終わるまで実行されない.) Console.WriteLine("SimpleMethod End"); // "SimpleMethod End"と出力. } // LongProcMethodの定義 static void LongProcMethod() { // 実行前 Console.WriteLine("LongProcMethod Begin"); // "LongProcMethod Begin"と出力. // 5秒休止で疑似的に長くかかる処理にする. Thread.Sleep(5000); // 5000ミリ秒休止. // 実行後 Console.WriteLine("LongProcMethod End"); // "LongProcMethod End"と出力. } }
実行すると、
![最初はこう。](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125183218.png)
最初はこう。
![次はこう](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125183258.png)
次はこう。
![最後はこう](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125183330.png)
最後はこう。
LongProcMethodのThread.Sleepをawait Task.Delayにしてみる。
そうすると、LongProcMethodもasyncにしないといけない。
// 名前空間の登録 using System; // 共通データ型と基本クラス(System名前空間) using System.Threading; // マルチスレッド(System.Threading名前空間) using System.Threading.Tasks; // タスク(System.Threading.Tasks名前空間) // MainClassの定義 class MainClass { // Mainの定義 static void Main() { // 実行前 Console.WriteLine("Main Begin"); // "Main Begin"と出力. // SimpleMethodを実行. SimpleMethod(); // SimpleMethodを呼ぶ. // SimpleMethodを抜けた後.(awaitで抜けた直後にここは実行される.) Console.WriteLine("SimpleMethod After"); // "SimpleMethod After"と出力. // 10秒待つ. Thread.Sleep(10000); // 10000ミリ秒休止. // 実行後 Console.WriteLine("Main End"); // "Main End"と出力. } // SimpleMethodの定義 static async void SimpleMethod() // awaitのあるメソッドにはasyncを付けないといけない. { // 実行前 Console.WriteLine("SimpleMethod Begin"); // "SimpleMethod Begin"と出力. // Task.Runで指定のActionを実行. await Task.Run(() => // awaitでこの処理を待つ. { // LongProcMethod実行前 Console.WriteLine("LongProcMethod Before"); // "LongProcMethod Before"と出力. // LongProcMethodを実行. LongProcMethod(); // LongProcMethodを呼ぶ. // LongProcMethod実行前 Console.WriteLine("LongProcMethod After"); // "LongProcMethod After"と出力. }); // 実行後(上のawaitの付いたタスクが終わるまで実行されない.) Console.WriteLine("SimpleMethod End"); // "SimpleMethod End"と出力. } // LongProcMethodの定義 static async void LongProcMethod() // asyncにする. { // 実行前 Console.WriteLine("LongProcMethod Begin"); // "LongProcMethod Begin"と出力. // Task.Delayで5秒待つ. await Task.Delay(5000); // 5000ミリ秒待つ. // 実行後 Console.WriteLine("LongProcMethod End"); // "LongProcMethod End"と出力. } }
とすると、
![最初こうなって](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125183832.png)
最初こうなって、
![次こうなって](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125183858.png)
次こうなって、
![最後こうなる](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125183953.png)
最後こうなる。
await Task.DelayだとLongProcMethodをすぐ抜けちゃって、"LongProcMethod After"に行ってしまい、Taskがすぐ終わって、"SimpleMethod End"まで行ってしまう。
となると、LongProcMethod自体もawaitしないといけない。
となると、ラムダ式をasyncにしないといけない。
で、こうなるわけだけど、VisualStudio2015だと、awaitする関数がvoidだとasync Taskにしないといけない。async voidにはできない。
たぶん、2013までは書けた気がするが。
C#の非同期メソッドの戻り値のvoidとかTaskがよくわからなかったので動かしてみた - Qiita
ここでも、それ言ってる。
(VS2012, VS2013準備するのも大変なので、それの検証は今回は割愛。)
で、こうすると、
![こうなって](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125185242.png)
こうなって、
![こうなって](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125185309.png)
こうなって、
![こうなる](https://cdn-ak.f.st-hatena.com/images/fotolife/B/BG1/20211125/20211125185413.png)
こうなる。
"SimpleMethod After"以外の"~ After"や"~ End"は、長い処理が終わってから通っている。
Sample/cs/async/async/src/async at master · bg1bgst333/Sample · GitHub