C# – Async Main

The Async Main feature was added in C# 7.1 and works with all overloads of the Main() method. To make the Main() method async, add async Task to the method signature, like this:

static async Task Main(string[] args)
{
	while (true)
	{
		Console.WriteLine("I'm looping");
		await Task.Delay(5000);
	}
}
Code language: C# (cs)

This is syntax sugar that compiles down to calling GetAwaiter().GetResult() on whatever you’re awaiting. In other words, it’s equivalent to doing the following (which you could do yourself in previous versions):

static void Main(string[] args)
{
	while (true)
	{
		Console.WriteLine("I'm looping");
		Task.Delay(5000).GetAwaiter().GetResult();
	}
}
Code language: C# (cs)

Async/await with a top-level statement

With the top-level statement feature (added in .NET 6), you can write programs without needing to explicitly define the Main() method. The compiler generates the right overload of Main() implicitly.

You can do async/await a top-level statement without doing anything special. Just add ‘await’ and the compiler will automatically generate the right async overload of Main() implicitly.

Here’s an example of using async/await in a top-level statement:

//Program entry point
while (true)
{
	Console.WriteLine("I'm looping");
	await Task.Delay(5000);
}
Code language: C# (cs)

This is equivalent to the async Task Main() code shown in the section above. The difference is that the Main() method is implicitly defined by the compiler.

Await a Task in Main

You can use Task.Run() in the Main() method. How you do this depends on exactly what you’re trying to accomplish. This is related to awaiting in Main(), but not exactly the same. Here’s an example of firing off two async lambdas with Task.Run():

static void Main(string[] args)
{
	Task.Run(async () =>
	{
		while (true)
		{
			Console.WriteLine($"I'm looping 1. Thread id = {Thread.CurrentThread.ManagedThreadId}");
			await Task.Delay(2000);
		}
	});

	Task.Run(async () =>
	{
		while (true)
		{
			Console.WriteLine($"I'm looping 2. Thread id = {Thread.CurrentThread.ManagedThreadId}");
			await Task.Delay(2000);
		}
	});

	Console.Read();
}
Code language: C# (cs)

This runs these two loops concurrently and outputs the following after a few seconds:

I'm looping 1. Thread id = 6
I'm looping 2. Thread id = 7
I'm looping 2. Thread id = 6
I'm looping 1. Thread id = 4
I'm looping 1. Thread id = 7
I'm looping 2. Thread id = 4Code language: plaintext (plaintext)

Leave a Comment