Do you use async/await for all IO-bound operations?
Updated by Zach Keeping [SSW] 1 year ago. See history
When using async, the thread is released back to the thread pool while waiting for IO, while the await keyword registers a callback that will be executed after IO completion.
The async/await pattern is most effective when applied “all the way down”. For ASP.NET web applications this means that the Controller Action – which is usually the entry point for a request into your application – should be async.
public ActionResult Gizmos(){var gizmoService = new GizmoService();return View("Gizmos", gizmoService.GetGizmos());}
❌ Figure: Figure: Bad example – This MVC Controller Action endpoint is not async so the thread assigned to process it will be blocked for the whole lifetime of the request
public async Task<ActionResult> GizmosAsync(){var gizmoService = new GizmoService();return View("Gizmos", await gizmoService.GetGizmosAsync());}
✅ Figure: Figure: Good example - This MVC Controller Action is async. The thread will be released back to the threadpool while waiting for any IO operations under the “gizmoService” to complete
Above code examples are based on: Using Asynchronous Methods in ASP.NET MVC 4
With these async/await patterns on .NET Core, our applications can handle very high levels of throughput.
Once an async/await based app is under heavy load, the next risk is from thread-pool starvation. Any blocking operations anywhere in the app can tie up threadpool threads – leaving fewer threads in the pool to handle the ongoing throughput. For this reason, the best practice is to ensure that all IO-bound operations are async and to avoid any other causes of blocking.
For more information on understanding and diagnosing thread pool starvation, read: Diagnosing .NET Core ThreadPool Starvation with PerfView (Why my service is not saturating all cores or seems to stall).
Further Information
Categories
Need help?
SSW Consulting has over 30 years of experience developing awesome software solutions.