8

I tried reading many articles and questions in stackoverflow regarding the real use of async/await, so basically asynchronous method calls but somehow I am still not able to decode of how does it provide parallelism and non blocking behavior. I referred few posts like these

Is it OK to use async/await almost everywhere?

https://news.ycombinator.com/item?id=19010989

Benefits of using async and await keywords

So if I write a piece of code like this

var user = await GetUserFromDBAsync();
var destination = await GetDestinationFromDBAsync();
var address = await GetAddressFromDBAsync();

Even though all the three methods are asynchronous but still the code will not go to the second line to get destination from database until it fully gets the user from the database.

So where is the parallelism and non blocking behavior of asyn/await here. It still waits to complete the first operation before executing the next line.

Or my total understanding is wrong about asyn?

EDIT

Any example would really help!

Pawan Nogariya
  • 8,330
  • 12
  • 52
  • 105
  • 3
    The point is, that your user interface won't freeze, while those async tasks are running. If you want to run multiple tasks at the same time, see https://stackoverflow.com/questions/25009437/running-multiple-async-tasks-and-waiting-for-them-all-to-complete – Sweeper Nov 24 '21 at 15:20
  • 3
    async.. await is not necessarily about parallelism. 'await...' does indeed wait for the called method to return, but it releases the thread it is running on until the async method returns. In doing so, the calling thread is free to do other processing, e.g. execute event-handlers to react to user interventions, thus keeping the UI responsive during the wait. – Johan Donne Nov 24 '21 at 15:20
  • 3
    You can't get to the next step of the code before the other one completes, the next code line (might) depend on the previous line (e.g. the previous should have values). The idea is not release current method, but it is to release current thread - if you have another 500 threads running, the next thread will gain CPU time. – st_stefanov Nov 24 '21 at 15:21
  • 1
    @st_stefanov The point is to avoid having 500 threads running. Ideally, the managed thread pool will only create approximately as many threads as you have CPU cores. Await doesn't mean another thread gains time; it means the *current* thread can go off and do something else. – Tech Inquisitor Nov 24 '21 at 15:54

2 Answers2

11

The point of async/await is not that methods are executed more quickly. Rather, it's about what a thread is doing while those methods are waiting for a response from a database, the file system, an HTTP request, or some other I/O.

Without asynchronous execution the thread just waits. It is, in a sense, wasted, because during that time it is doing nothing. We don't have an unlimited supply of threads, so having threads sit and wait is wasteful.

Async/await simply allows threads to do other things. Instead of waiting, the thread can serve some other request. And then, when the database query is finished or the HTTP request receives a response, the next available thread picks up execution of that code.

So yes, the individual lines in your example still execute in sequence. They just execute more efficiently. If your application is receiving many requests, it can process those requests sooner because more threads are available to do work instead of blocking, just waiting for a response from some I/O operation.

I highly recommend this blog post: There Is No Thread. There is some confusion that async/await is about executing something on another thread. It is not about that at all. It's about ensuring that no thread is sitting and waiting when it could be doing something else.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
3

You can execute them in parallel/concurrently and still await them in non-blocking manner withTask.WhenAll. You don't have to await each single async method call individually. So you have the performance gain and at the same time a responsive UI:

//create 3 "cold" tasks, that are not yet running
var userTask = GetUserFromDBAsync();
var destinationTask = GetDestinationFromDBAsync();
var addressTask = GetAddressFromDBAsync();

//start running and awaiting all of them at (almost) the same time
await Task.WhenAll(userTask, destinationTask, adressTask);

//get the cached results
var user = userTask.Result;
var destination = destinationTask.Result;
var address = addressTask.Result;
lidqy
  • 1,891
  • 1
  • 9
  • 11