【C#】async Main の使い方|非同期エントリポイント

C# 7.1 以降では、アプリケーションのエントリポイントである Main メソッドを async にすることが可能になりました。これにより、アプリケーションの起動直後から await を利用した非同期処理を自然に書けるようになります。この記事では async Main の使い方と注意点を解説します。

従来の Main と async Main の違い

従来はエントリポイントの Main メソッドで非同期処理を行いたい場合、Task.Wait()GetAwaiter().GetResult() を使って強制的に同期的に待つ必要がありました。C# 7.1 以降では Main 自体を async にできるため、自然に await を使えます。

async Main の基本構文

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("開始します…");
        await Task.Delay(2000); // 非同期処理を待機
        Console.WriteLine("2秒後に完了しました。");
    }
}

Main の戻り値を Task または Task<int> にすることで、非同期処理を直接記述できます。

戻り値のパターン

Main の戻り値は以下のパターンが許されています。

  • void Main(string[] args) (従来形式)
  • int Main(string[] args) (終了コードを返す)
  • Task Main(string[] args) (非同期処理)
  • Task<int> Main(string[] args) (非同期処理+終了コード)

Task<int> で終了コードを返す例

using System;
using System.Threading.Tasks;

class Program
{
    static async Task<int> Main(string[] args)
    {
        Console.WriteLine("処理を開始します…");
        await Task.Delay(1000);

        bool success = true;

        if (success)
        {
            Console.WriteLine("成功しました。");
            return 0; // 正常終了コード
        }
        else
        {
            Console.WriteLine("失敗しました。");
            return 1; // 異常終了コード
        }
    }
}

このように return で整数を返すと、OS に終了コードを渡せます。バッチ処理や CI 環境などで有効です。

注意点

  • async Main が使えるのは C# 7.1 以降。プロジェクトの LangVersion を確認しましょう。
  • Mainasync void は指定できません。必ず Task または Task<int> にします。
  • 非同期処理の例外はタスクに伝播するため、例外処理を try-catch で適切に行う必要があります。

まとめ

C# 7.1 以降では Main を非同期化できるため、アプリケーションのエントリポイントから自然に await を利用できます。終了コードも Task<int> で返せるため、コンソールアプリの運用がより柔軟になります。従来の Wait() を使った同期処理から移行することで、よりシンプルで読みやすいコードが書けます。