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()
を使った同期処理から移行することで、よりシンプルで読みやすいコードが書けます。