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を確認しましょう。Mainにasync voidは指定できません。必ずTaskまたはTask<int>にします。- 非同期処理の例外はタスクに伝播するため、例外処理を
try-catchで適切に行う必要があります。
まとめ
C# 7.1 以降では Main を非同期化できるため、アプリケーションのエントリポイントから自然に await を利用できます。終了コードも Task<int> で返せるため、コンソールアプリの運用がより柔軟になります。従来の Wait() を使った同期処理から移行することで、よりシンプルで読みやすいコードが書けます。

