MathuSum Mut
MathuSum Mut

Reputation: 2825

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?

Upvotes: 7

Views: 4178

Answers (4)

Paulo Morgado
Paulo Morgado

Reputation: 14856

All calls are synchronous. It's the await that can be asynchronous if the returned awaitable is not complete.

Upvotes: -1

Gabriel Luci
Gabriel Luci

Reputation: 41008

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.

Upvotes: 11

Kevin Gosse
Kevin Gosse

Reputation: 39037

  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).

Upvotes: 1

canton7
canton7

Reputation: 42350

  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.

Upvotes: 3

Related Questions