C# Feature - async Main
async Main
Section titled “async Main”async Main allows a console application’s entry point to return Task or Task<int>, so startup code can await asynchronous operations directly instead of blocking on them.
Introduced In
Section titled “Introduced In”This feature was introduced in C# 7.1 (2017).
Why This Feature Exists
Section titled “Why This Feature Exists”Before C# 7.1, async startup logic usually meant forcing asynchronous code into synchronous flow with .Result, .Wait(), or .GetAwaiter().GetResult(). That approach is harder to read and can hide failure behavior.
With async Main, the entry point follows the same async style as the rest of the codebase.
Supported Signatures
Section titled “Supported Signatures”static async Task Main()static async Task Main(string[] args)static async Task<int> Main()static async Task<int> Main(string[] args)When To Use It
Section titled “When To Use It”- Use it in console applications that call HTTP APIs, databases, files, queues, or any other async dependency during startup.
- Use
Task<int>when the process should return an exit code. - Prefer it over blocking on async work manually.
Before
Section titled “Before”static int Main(){ RunAsync().GetAwaiter().GetResult(); return 0;}static async Task Main(){ await RunAsync();}Practical Example
Section titled “Practical Example”using System.Net.Http;
static async Task<int> Main(string[] args){ using var client = new HttpClient();
try { string health = await client.GetStringAsync("https://example.com/health"); Console.WriteLine($"Service health: {health}"); return 0; } catch (HttpRequestException ex) { Console.Error.WriteLine($"Startup check failed: {ex.Message}"); return 1; }}Common Pitfalls
Section titled “Common Pitfalls”- Do not mix
async Mainwith.Resultor.Wait()unless there is a very specific reason. async voidis not a valid entry point signature.- Startup code can still fail fast, so exception handling should be deliberate rather than implicit.
Version Notes
Section titled “Version Notes”- C# 7.1 introduced asynchronous entry points.
- C# 9 top-level statements can also produce an async entry point implicitly when
awaitis used.