Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are awaits in async method called without await still asynchronous?

Consider the following code:

public static void Run() {
    DoStuffAsync();
}

public static async Task DoStuffAsync() {
     PerformCalc();
     await DoLongTaskAsync();
     PerformAnotherCalc();
}

Let's say I call Run(). I have a few questions regarding behaviour:

  1. Will PerformCalc() be called synchronously on the same thread as the one that called Run()?
  2. Will DoLongTaskAsync() be called asynchronously or synchronously? In other words, will/can PerformAnotherCalc() be called before DoLongTaskAsync() has finished?
  3. Subsequently, can the DoStuffAsync() method return before execution of DoLongAsyncTask() has completed?
like image 557
MathuSum Mut Avatar asked Aug 15 '19 12:08

MathuSum Mut


People also ask

What happens when you call async method without await?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.

Can we call await without async?

You can use the await keyword on its own (outside of an async function) within a JavaScript module. This means modules, with child modules that use await , wait for the child module to execute before they themselves run.

Is async await really asynchronous?

In computer programming, the async/await pattern is a syntactic feature of many programming languages that allows an asynchronous, non-blocking function to be structured in a way similar to an ordinary synchronous function.

Can we have a async function with and without await?

Async function without await insideWe can declare a function as async without using any await . In this case, the execution is not paused and your code will be executed in a non-blocking manner (asynchronous - no waiting). It is the same as not declaring that same function with async .


Video Answer


3 Answers

Async methods always start running synchronously. The magic happens at await, but only when await is given a Task that has not completed.

In your example, this is what will happen when you call Run():

  1. Jump to DoStuffAsync()
  2. Jump to PerformCalc()
  3. Jump to DoLongTaskAsync()
  4. If DoLongTaskAsync() is a truly asynchronous operation and returns an incomplete Task, then await does its job and DoStuffAsync() returns an incomplete Task to Run().
  5. Since the task is not awaited, Run() completes.
  6. When DoLongTaskAsync() completes, DoStuffAsync() resumes, and jumps to PerformAnotherCalc().

All of that can happen on the same thread.

So to answer your questions:

  1. Yes. If it is an async method, it might end up going out and doing things on other threads. But it will start synchronously on the same thread.
  2. DoLongTaskAsync() will be called asynchronously, but PerformAnotherCalc() will not be called before DoLongTaskAsync() finishes, because you used await.
  3. Yes. This is how await works. It will return an incomplete Task (that is, only if DoLongTaskAsync() is truly asynchronous and returns an incomplete Task). Then once DoLongTaskAsync() finishes, execution of DoStuffAsync() resumes where it left off.
like image 59
Gabriel Luci Avatar answered Oct 16 '22 21:10

Gabriel Luci


  1. Will PerformCalc() be called synchronously on the same thread as the one that called Run()?

Yes.

  1. Will DoLongTaskAsync() be called asynchronously or synchronously? In other words, will PerformAnotherCalc() be called before DoLongTaskAsync() has finished?

It will be called synchronously, but it may return a Task before the "Long Task" operation has finished. Either way, the Task it returns is awaited, so PerformAnotherCalc will not be called until the Task returned from DoLongTaskAsync completes.

  1. Subsequently, can the DoStuffAsync() method return before execution of DoLongAsyncTask() has completed?

The DoStuffAsync method will return when it hits the first await (iff the Task being awaited is pending). That's how async methods work -- they run synchronously up until the first await of a Task which is pending, and then they return a Task which will complete when the whole method has executed.

If might be that DoLongTaskAsync returns a Task which has already completed: in that case, DoStuffAsync won't return until PerformAnotherCalc has returned. If DoLongTaskAsync returns a Task which is still pending, then DoStuffAsync will return at that point, and it will return a Task which completes once the Task returned from DoLongTaskAsync has completed, and PerformAnotherCalc has returned.

like image 2
canton7 Avatar answered Oct 16 '22 19:10

canton7


  1. Yes
  2. No
  3. Yes

Put otherwise, if you consider those methods:

public static void Run1() {
    DoStuffAsync();
    Console.WriteLine("Done");
}

public static async Task Run2() {
    await DoStuffAsync();
    Console.WriteLine("Done");
}

public static async Task DoStuffAsync() {
     PerformCalc();
     await DoLongTaskAsync();
     PerformAnotherCalc();
}

In Run2, you are guaranteed that "Done" will be displayed after PerformAnotherCalc. In Run1, "Done" will be displayed after PerformCalc but before PerformAnotherCalc (assuming that DoLongTaskAsync is actually asynchronous, which depends of its implementation).

like image 1
Kevin Gosse Avatar answered Oct 16 '22 19:10

Kevin Gosse