DEV Community

Cover image for Understanding Async/Await
Taki089.Dang
Taki089.Dang

Posted on

Understanding Async/Await

Let's dive deeper into the behavior of async/await and how it changes the program's flow in two scenarios:

  1. When we don't use 'await', tasks are started but not awaited, allowing the program to continue immediately.

  2. When we use 'await', the program pauses and waits for the task to finish before proceeding.

I have Order Pizza and Order Drink like this:

class Program
{
    public static async Task OrderPizza()
    {
        Console.WriteLine("Ordering Pizza...");
        await Task.Delay(1000); // Simulate 1 seconds of work
        Console.WriteLine("Pizza ready!");
    }

    public static async Task OrderDrink()
    {
        Console.WriteLine("Ordering Drink...");
        await Task.Delay(2000); // Simulate 2 seconds of work
        Console.WriteLine("Drink ready!");
    }
}

Enter fullscreen mode Exit fullscreen mode

Understanding the two Code Snippets.

Here are the two scenarios you're asking about:

1. Without await:

    public static async Task Main(string[] args)
    {
        OrderPizza();
        Console.WriteLine("This is synchronous script");
        OrderDrink(); 
    }

Enter fullscreen mode Exit fullscreen mode

2. With await:

    public static async Task Main(string[] args)
    {
        await OrderPizza();  // Waits for pizza to completenchat
        Console.WriteLine("This is synchronous script");
        await OrderDrink();  // Waits for drink to complete
    }

Enter fullscreen mode Exit fullscreen mode

Okie let's start with:

How they Work Internally

1. Without await:

Image description

(Note: The use of MainThread for simplification is understandable, but clarifying how the ThreadPool handles tasks would make it more precise).

Code Behavior:

  1. OrderPizza() is called, but it does not blocked the main thread. It starts running in the background if it is asynchronous.
  2. The program immediately executes Console.WriteLine("This is synchronous script")
  3. Then, it calls OrderDink() without waiting for OrderPizza() to finish

Result:

  • The "This is synchronous script" message appears before the pizza or drink task complete.
  • Task for OrderPizza and OrderDrink run in parallel (overallap);

Output Example (Non-deterministic due to overlapping):

Ordering Pizza...
Successfully
Ordering Drink... --> actual print in the terminal when the program completed

Drink ready!
Pizza ready! -->Do not show in terminal b/c it runs and completes in the Background task
Enter fullscreen mode Exit fullscreen mode

Image description

2. With Await

Code Behavior:

  1. await OrderPizza is called, and the program waits until the OrderPizza task finishes
  2. After OrderPizza completes, Console.WriteLine("This is synchronous script") is executed.
  3. Then, await OrderDrink is called, and the program waits again for OrderDrink to finish.

Result:

  • Tasks run sequentially.
  • The pizza must finish before moving to the "This is synchronous script" message, and the drink must finish before proceeding further. (The program must wait for each task to complete before moving to the next step)
Ordering Pizza...
Pizza ready!
This is synchronous script
Ordering Drink...
Drink ready!
Enter fullscreen mode Exit fullscreen mode

Image description

Summary: Key Differences Between the Two

Aspect Without await With await
Execution Order Non-sequential, overlaps tasks. Sequential, tasks execute in order.
Message Timing next script run immediately. Next script waits for completion.
Use Case Use when task order doesn’t matter. Use when task order matters.
Thread Blocking Non-blocking but lacks control. Non-blocking with full control.

When to Use Each?

Without await:

Use this approach when tasks can run independently, and you don’t care about the order or timing of their completion. For example, sending analytics data to a server while continuing with other work.

With await:

Use this approach when the task order matters, or the next step depends on the completion of the previous task. For example, processing a user’s order where pizza preparation must finish before delivering the drink.

Top comments (0)