C# Async Main

By FoxLearn 1/21/2025 8:22:57 AM   11
The Async Main feature, introduced in C# 7.1, allows you to make the Main() method asynchronous.

For example:

static async Task Main(string[] args)
{
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine($"Task {i + 1} is starting");
        await PerformTaskAsync(i + 1);
    }
}

static async Task PerformTaskAsync(int taskId)
{
    await Task.Delay(1000);  // Simulate some async work
    Console.WriteLine($"Task {taskId} completed");
}

In this example, we’re performing asynchronous tasks and waiting for each one to complete using await Task.Delay(1000) to simulate an asynchronous operation. The Main method will execute each task in sequence with a delay of one second between them.

Prior to C# 7.1, you would have to explicitly handle the task awaiting in the Main() method as follows:

static void Main(string[] args)
{
    for (int i = 0; i < 5; i++)
    {
        Console.WriteLine($"Task {i + 1} is starting");
        PerformTaskAsync(i + 1).GetAwaiter().GetResult();
    }
}

static async Task PerformTaskAsync(int taskId)
{
    await Task.Delay(1000);
    Console.WriteLine($"Task {taskId} completed");
}

While both approaches work, the async version is clean, especially when using the await keyword in the Main() method.

Async/Await with Top-Level Statements

With .NET 6 and later, you can take advantage of top-level statements, eliminating the need for explicitly defining the Main() method.

Here’s an example that uses async/await in a top-level program:

// Program entry point
for (int i = 0; i < 5; i++)
{
    Console.WriteLine($"Task {i + 1} is starting");
    await PerformTaskAsync(i + 1);
}

static async Task PerformTaskAsync(int taskId)
{
    await Task.Delay(1000);  // Simulate async operation
    Console.WriteLine($"Task {taskId} completed");
}

This approach is functionally equivalent to using the async Task Main() method but eliminates the need for the Main method definition.

Multiple Async Tasks in Main

You can also run multiple async tasks concurrently using Task.Run().

static void Main(string[] args)
{
    Task.Run(async () =>
    {
        while (true)
        {
            Console.WriteLine($"Task 1 running on thread {Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
        }
    });

    Task.Run(async () =>
    {
        while (true)
        {
            Console.WriteLine($"Task 2 running on thread {Thread.CurrentThread.ManagedThreadId}");
            await Task.Delay(2000);
        }
    });

    Console.Read();
}

The output shows how the tasks run on different threads and alternate in execution:

Task 1 running on thread 4
Task 2 running on thread 7
Task 1 running on thread 4
Task 2 running on thread 7
...

Each task runs concurrently, demonstrating how to handle multiple asynchronous operations in parallel within the Main() method.