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..
}
Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
scroll top