Immediately awaiting an asynchronous call [duplicate]
https://softwareengineering.stackexchange.com/questions/361693
-
23-01-2021 - |
Question
While working on an inherited project, I noticed the original dev(s) created many asynchronous functions that never seem to take advantage of being, well, asynchronous. For example:
// The async method
private async Type myFuncAsync() { .. gets something from DB .. }
// Example of how the method is consistently utilized
public async Type seaHorses() {
var seaPony = await myFuncAsync();
.. do stuff ..
}
From my understanding, this is pointless because if you're always immediately calling await
when firing off an async
method, then you're really just writing synchronous code. It'd be no different then writing:
// The sync method
private Type myFunc() { .. gets something from DB .. }
// Example of how the method is consistently utilized
public Type seaHorses() {
var seaPony = myFunc();
.. do stuff ..
}
Whereas what I expect an efficient use of an async
method to look like:
// The async method
private async Type myFuncAsync() { .. gets something from DB .. }
// Example of how the method is consistently utilized
public async Type seaHorses() {
var loveSeaHorses = myFuncAsync();
.. do stuff ..
await loveSeaHorses;
}
Is this assumption correct? Is there any reason for or against having methods defined as async
that always have await
immediately called?
Note: From some research, I have a vague understanding that immediately calling await
means that the main thread continues execution. In the example above, it means that work will be done on the main thread for whatever comes after seaHorses()
until myFuncAsync()
inside seaHorses()
is done. Which leads me to point out the following scenario and ask if this is actually an improper utilization of asynchronous programming:
// The async method
private async Type myFuncAsync() { .. gets something from DB .. }
// Example of how the method is consistently utilized
public async Type seaHorses() {
var seaPony = await myFuncAsync();
.. do stuff ..
}
// Main Thread
Program {
.. do stuff ..
var waterHorses = await seaHorses();
.. do stuff..
}
Solution
I think you misunderstand the await
call. What async and await do is allow the thread you are executing on (not just the main thread) to continue working. The mechanism that supports this is called a continuation. So instead of the thread blocking (waiting) for IO, it can be execute other tasks. When the task in the await
completes, the thread will continue on from that point.
The value of this may not seem intuitive but contemporary machines can only support so many OS threads before the overhead of thread management outweighs the advantages. This kind of 'lightweight threading' allows for more efficient use of the system level threads. For example a web server could support many concurrent requests using a handful of threads instead of using hundreds which was typical in the not-so-distant past.