Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when you await an asynchronous task in C#?

From what I understood in all async/await tutorials in C#, I get that when we define an async method, it means that we can add the await keyword inside it with a task as a parameter, to make the method return to caller if the task is too long. The method can then resume when task is completed.

public void MyMainMethod()
{
   DoSomethingAsync();
   KeepOnDoingOtherStuff();
}

public async Task DoSomethingAsync()
{
   //Do whatever
   await LongOperation();
   // Rest of the method that is executed when the long operation is 
    //finished.

}

So here while the long operation is going on, as it is awaited, the DoSomething async gives hand to the MainMethod and the KeepOnDoingOtherStuff is executed. OK

Now my problem is if my DoSomethingAsync itself is awaited. In this case:

public async void MyMainMethod()
{
   await DoSomethingAsync();

   //Here is a critical method that I want to execute only when 
     //DoSomethingAsync is finished

   CriticalStuff();
}

public async Task DoSomethingAsync()
{
   //Do whatever
   await LongOperation();
   // Rest of the method that is executed when the long operation is 
    //finished.

}

Now I await my DoSomethingAsync so that I am sure that it doesn't go further, but the problem is that the DoSomethingAsync () still gives hand to the caller when it awaits the LongOperation(), and my Main method resumes, which I don't want because it executes my critical thing.

There is something I quite miss in asynchronous logic, what then would be the point to "await" a method that has asynchronous methods inside it?

I would very much appreciate a solution to my problem.

Thanks in advance.

like image 606
Zeppelin Avatar asked Jan 28 '23 02:01

Zeppelin


1 Answers

I think the mismatch here comes from these words:

to make the method return to caller if the task is too long.

await isn't about long, exactly. It is about asynchronous. If something takes a long time but happens on local CPU then sure: it isn't really a great fit for await (although you can use the await machinery as a convenient way of pushing things to a worker thread, and then rejoin a sync-context thread when it completes).

The better example, though, is when the task is external; it could be a call to a SQL database, or to redis, or via http, or to another process over some kind of IO layer, or waiting for socket data. Note that even talking to physically local SSD storage can involve long waits, at least as measured by CPU speeds. When the local thread would be doing nothing except blocking (waiting for a reply), then : in many cases there are much better things that the thread could be doing.

In the case of a client app, those "better things" include painting the UI and responding to input. In the case of a server app, those "better things" include servicing other concurrent requests / load.


When measured in this way: await acts as an effective way of writing code that needs data from external sources, but doesn't want to just block the current thread while that data arrives. If that isn't your scenario: await might not be for you.

like image 148
Marc Gravell Avatar answered Feb 04 '23 09:02

Marc Gravell