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.
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.