As an example I have an ASP.NET Core API controller
fetching some data from a service and 2
possible ways to implement the controller method:
With async/await:
[HttpGet]
public async Task<IActionResult> GetSomeDataAsync()
{
return await someService.GetSomeDataAsync();
}
Without async/await:
[HttpGet]
public Task<IActionResult> GetSomeDataAsync()
{
return someService.GetSomeDataAsync();
}
Which one of these two is better? The key here is that there is only 1 call to another async method (someService.GetSomeDataAsync()
).
ASP.NET Core apps should be designed to process many requests simultaneously. Asynchronous APIs allow a small pool of threads to handle thousands of concurrent requests by not waiting on blocking calls. Rather than waiting on a long-running synchronous task to complete, the thread can work on another request.
This is important to keep in mind. If await is not used in the body of an async method, the C# compiler generates a warning, but the code compiles and runs as if it were a normal method. This is incredibly inefficient, as the state machine generated by the C# compiler for the async method is not accomplishing anything.
When to use Asynchronous Controller. Asynchronous action methods are useful when an action must perform several independent long running operations. Suppose we have three operations which takes 500, 600 and 700 milliseconds. With the synchronous call, total response time would be slightly more than 1800 milliseconds.
When we don't want to return a result from our async method, we should always return a Task. To validate our asynchronous operations, we have to use the await keyword while calling that operation. When we convert our synchronous code to asynchronous, we have to use the async and await keywords all the way up the chain.
According to ASP.NET Core Performance Best Practices from ASP.NET team:
Avoid blocking calls
ASP.NET Core apps should be designed to process many requests simultaneously. Asynchronous APIs allow a small pool of threads to handle thousands of concurrent requests by not waiting on blocking calls. Rather than waiting on a long-running synchronous task to complete, the thread can work on another request.
A common performance problem in ASP.NET Core apps is blocking calls that could be asynchronous. Many synchronous blocking calls lead to Thread Pool starvation and degraded response times.
Avoid synchronous read or write on HttpRequest/HttpResponse body
All I/O in ASP.NET Core is asynchronous. Servers implement the Stream interface, which has both synchronous and asynchronous overloads. The asynchronous ones should be preferred to avoid blocking thread pool threads. Blocking threads can lead to thread pool starvation.
Prefer ReadFormAsync over Request.Form
Use HttpContext.Request.ReadFormAsync
instead of HttpContext.Request.Form
. HttpContext.Request.Form
can be safely read-only with the following conditions:
ReadFormAsync
, andHttpContext.Request.Form
Optimize data access and I/O
Interactions with a data store and other remote services are often the slowest parts of an ASP.NET Core app. Reading and writing data efficiently is critical for good performance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With