Home > Software design >  In C#, if any asynchronous operation in a method makes an entire method async, why would I need more
In C#, if any asynchronous operation in a method makes an entire method async, why would I need more

Time:07-27

Why doesn't one await statement make all other statements in the same method async-await calls?

From MS docs:

static async Task<Toast> MakeToastWithButterAndJamAsync(int number)
{
    var toast = await ToastBreadAsync(number);
    ApplyButter(toast);
    ApplyJam(toast);

    return toast;
}

On the page it says,

Composition with tasks

You have everything ready for breakfast at the same time except the toast. Making the toast is the composition of an asynchronous operation (toasting the bread), and synchronous operations (adding the butter and the jam). Updating this code illustrates an important concept:

Important

The composition of an asynchronous operation followed by synchronous work is an asynchronous operation. Stated another way, if any portion of an operation is asynchronous, the entire operation is asynchronous.

Later on in the final version, one of the methods shows two await statements. Why? If the method has the first await on Task.Delay, why do I need another await on the second Task.Delay? Wouldn't the Task.Delay make this async thread "await" here anyway?

private static async Task<Bacon> FryBaconAsync(int slices)
        {
            Console.WriteLine($"putting {slices} slices of bacon in the pan");
            Console.WriteLine("cooking first side of bacon...");
            await Task.Delay(3000);
            for (int slice = 0; slice < slices; slice  )
            {
                Console.WriteLine("flipping a slice of bacon");
            }
            Console.WriteLine("cooking the second side of bacon...");
            await Task.Delay(3000);
            Console.WriteLine("Put bacon on plate");

            return new Bacon();
        }

This did not tell me the why: Why do we need more than one `await` statement in a C# method?

Nor this,

C# Async Await with Synchronous and Asynchronous operation

CodePudding user response:

Task.Delay doesn't delay your current task. It creates another task that waits for that amount. So if you just do Task.Delay(123) you are spawning another task that waits for 123 ms, but your current task doesn't wait for that spawned task to finish. In order to make your current task wait for 123 ms as well, you need to await Task.Delay(123), which makes the current task wait for the spawned task, which waits for 123 ms. Because await pauses the current task's execution at that point to wait for the given other task to complete.


Note: Please note the comment by Theodor Zoulias:

It's better to say that the Task.Delay creates a task that will complete after that amount of time. There is no waiting taking place internally.

CodePudding user response:

I think there is a misunderstanding here. awaits are there so that the next statement executes after the work is done.

Let's imagine a piece of code that requires a sequence of steps.

async Task<bool> ProcessAsync() 
{
   var data = await GetDataAsync();
   await SendDataOrThrowAsync(data);
   return true; // Success
}

The 1st await, easy, you cannot send data before you get it. The 2nd await is there so that return true is executed only when the sending is finished.

Without the 2nd await the contract changes.

async Task<bool> ProcessAsync() 
{
   var data = await GetDataAsync();
   SendDataOrThrowAsync(toast); // don't wait just start
   return true; // Success
}

A true here means that we started sending not that we sent it.

  • Related