Lijin John Lijin John - 12 days ago 4
C# Question

understanding Async and Await in C#

I am trying to learn Async and Await in C#. I have three methods and when I try to call all this three methods it makes me wonder how the Asynchronous call actually works in C#.

class Content {

public async Task<string> Delay1() {
await Task.Delay(5000);
return "hello";
}
public async Task<string> Delay2() {
await Task.Delay(5000);
return "hello";
}
public async Task<string> Delay3() {
await Task.Delay(5000);
return "hello";
}
public async Task Print() {
Console.WriteLine(await Delay1());
Console.WriteLine(await Delay2());
Console.WriteLine(await Delay3());
}
}


So, When I make a call to this method:

static void Main() {
new Content().Print();
Console.Read();
}


I am supposed to get all the three methods at the same time after a delay of 5 seconds but instead my
Delay2()
method gets called after 5 seconds of the
Delay1()
method and
Delay3()
method gets called after 5 seconds of the
Delay2()
method.

Can someone help me understand the working of Async method in C#?

UPDATE 1
Async and Await are suppose to be Asynchronous, then why is my regular statement getting stopped from execution

public async Task Print()
{
Console.WriteLine(await Delay1());

Console.WriteLine("this is regular flow");
}

Answer

It is NOT true as some other answers have stated that async is not a form of concurrency. Ansynchronous programming IS (Yes it is) a form of concurrency. But, having said that, it does not mean the work will need less time. The work will still take the same amount of time (possibly longer due to context switching). But the trick is the work will be done at the same time without waiting for previous work to finish (Delay1 then Delay2 and then Delay3). Let me explain all this using your code.

Here is what you are doing in your code in Print method: Lets call the thread executing Print P1

  1. Do Delay1 AND when it returns then go to 2 below. In Delay1 method another thread is given the task to sleep. Lets call it T1. T1 please sleep for 5 secs and then return "hello".
  2. Do Delay2 AND when it returns then go to 3 below. In Delay2 method another thread is given the task to sleep. Lets call it T2. T2 please sleep for 5 secs and then return "hello".
  3. Do Delay3 AND when it returns then go to next line (there is no next line so program will complete). In Delay3 method another thread is given the task to sleep. Lets call it T3. T3 please sleep for 5 secs and then return "hello".

So your print method method calls Delay1 and waits for it to return. Then it calls Delay2 and waits for it to return. Then 3 and waits for it to return. All those will return after 5 secs of sleeping (each).

So you may ask: "then what is the point of all this"?

The point is that in your print method you can call all of them at the same time: do Delay1, do Delay2 and do Delay3 and when they are all done then go to next line.

So what does that get you?

Well if you were calling some web service in your Delay methods and each one takes 10 seconds to return, you are calling them ALL AT THE SAME time (almost) so all three will start getting to work. Chances are they will all return after a little over 10 seconds. So you basically sent them all to work at the same time hence "Concurrency". If you do not call them asynchronously, then Delay1 needs to complete (10 Secs), then Delay2 (10 secs) then Delay3 (10 secs) so 30 seconds all in total.

Think about it like this:

You are a manager at McDonald's. You have many employees (thread pool) and you need them to do work (Delay1, Delay2 and Delay3). What is better to tell 1 employee to do Delay1 then Delay2 and then Delay3 or assign 3 different employees (threads from thread pool) and ask 1 employee to do Delay1 and tell second employee to do Delay2 and not to wait for Delay1 to complete and ask 3rd employee to do Delay3. Obviously you would choose 3 employees.

Now in the world of thread pools it is a bit different. It is possible that the the same thread is chosen for 2 tasks because one thread did the job and came back to the pool and then was given another task. In your example, it is highly unlikely because they need to sleep for 5 secs. There is only 1 way to do that.

Please note in some cases, one task depends on another and you have no choice but to wait. For example, if Delay1 was getting a file from a remote machine and Delay2 was getting another file, and Delay3 would process both files then Delay1 and Delay2 can be done "Concurrently" but Delay3 will need to wait for them to return before it can start.

Comments