スポンサーリンク

[C#]非同期Mainメソッドまとめ(async/await)

非同期Mainメソッドとは

今回は非同期Mainメソッドについてです。
この機能はコンソールアプリを作るときにMainメソッド内で非同期メソッド使いたい、というときに簡単にコードを書けるようにということで生まれたものみたいです。

It is very common when learning C#, when writing console-based utilities, and when writing small test apps to want to call and await async methods from Main. Today we add a level of complexity here by forcing such await‘ing to be done in a separate async method, which causes developers to need to write boilerplate like the following just to get started:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-7.1/async-main

非同期Mainメソッドを使わない場合、Mainメソッドとは別に非同期メソッドを定義して、ということをしなくてはいけないのでちょっと面倒でした。

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace HttpClient_Test {
    class Program {
        static void Main(string[] args) {
            //Resultプロパティを取得して間接的にGetAsyncメソッドの完了を待機
            HttpStatusCode statusCode = GetBodyStringAsync().Result;
            Console.WriteLine(statusCode);
        }

        //メソッド内でawaitを使っているのでasyncを付ける
        static async Task<HttpStatusCode> GetBodyStringAsync() {
            //HttpClientのインスタンスを作成
            HttpClient client = new HttpClient();

            //Get(ここが非同期)
            HttpResponseMessage response = await client.GetAsync("https://yaspage.com");

            //StatusCodeを返す
            return response.StatusCode;
        }
    }
}

非同期Mainメソッドの使い方

Mainメソッドにasyncキーワードを付けると非同期Mainメソッドになります。
非同期MainメソッドはMainメソッド内でawaitキーワードを使用するときに使います。

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program {
    //asyncを付けると非同期Mainメソッドになる
    static async Task Main(string[] args) {
        Console.WriteLine("非同期Mainメソッドのてすと");

        var client = new HttpClient();
        //Mainメソッド内でawaitを使うときは非同期Mainメソッドにする必要がある
        var response = await client.GetAsync("https://yaspage.com/");

        Console.WriteLine(response.StatusCode);
    }
}

で、awaitってどんな時に使うの?というと、
Task型、Task<T>型を返すメソッドを使いたいときに使います。
Task型、Task<T>型を返すメソッドにはメソッド名の後ろに「~Async」とか付いています。

「~Async」が付いているメソッドは、時間のかかる処理を別スレッドで実行してその間メインスレッドが止まらないようにするメソッドなので、awaitを使わずにMainメソッド内でこのメソッドを実行するとまだ別スレッドの処理が終わってないのにMainメソッドが終了してしまう、ということになります。
ということで、awaitを使って別スレッドの処理が終わるまで待機してから次の行を実行するというふうにします。

上のコードを実行すると以下のようにレスポンスのステータスコードがちゃんと表示されます。

非同期Mainメソッドのてすと
OK

非同期Mainメソッドの戻り値

ここまでスルーしていましたが、上のコードのMainメソッドの戻り値がTaskになっているのに気付いたでしょうか?
普通のMainメソッド(同期Mainメソッド)の戻り値voidの非同期版が戻り値Taskになります。戻り値なしの非同期Mainメソッドってことです。
普通のMainメソッドとの比較はこんな感じ。

//戻りなしの同期Mainメソッド
static void Main() {}
//戻り値なしの非同期Mainメソッド
static async Task Main() {}

//戻り値ありの同期Mainメソッド
static int Main() {}
//戻り値ありの非同期Mainメソッド
static async Task<int> Main() {}

Mainメソッドの戻り値の使い方についてはこちらの記事にまとめました。

[C# 入門] コマンドライン引数とプログラムの終了コード
プログラムを実行する際に文字列のパラメーターを渡すことが出来ます。これをコマンドライン引数といいます。また、プログラムの終了時にint型の戻り値(終了コード)を返すことが出来ます。引数?戻り値??という人は メソッドの使い...

非同期Mainメソッドの省略

C#9からMainメソッドを省略してコードが書けるようになっているのでこんな感じに書くことができます。

using System;
using System.Net.Http;

Console.WriteLine("非同期Mainメソッドのてすと");

var client = new HttpClient();
var response = await client.GetAsync("https://yaspage.com/");

Console.WriteLine(response.StatusCode);

asyncやらTaskが出てこないので簡潔に書くことが出来ます。


¥3,520 (2022/04/28 19:09時点 | Amazon調べ)
¥2,750 (2022/04/28 19:18時点 | Amazon調べ)

C# プログラミング講座に戻る

コメント