Reputation: 1117
I have watched a few videos on youtube by Les Jackson, on how to create a .net core api. Les uses this approach for a method in his controller
public ActionResult<IEnumerable<Command>> GetAllCommands()
{
var commandItems = _repository.GetAppCommands();
return Ok(commandItems);
}
However I have just read an article in a book that uses this approach
public async Task<ActionResult<IEnumerable<Data.CityDataClass>>> GetCities()
{
return await _repository.GetCities();
}
From my thinking is the second method an overkill using the "async" declaration? The first method wont return anything until it has the results anyway.
Thanks
Upvotes: 2
Views: 939
Reputation: 26362
You can understand this better if you read this article on I/O threads
To use asynchronous and parallel features of the .NET properly, you should also understand the concept of I/O threads.
Not everything in a program consumes CPU time. When a thread tries to read data from a file on disk or sends a TCP/IP packet through network, the only thing it does is delegate the actual work to a device - disk or network adapter - and wait for results.
I/O thread is an abstraction intended to hide work with devices behind a simple and familiar concept. The main point here is that you don’t have to work with those devices in a different way, you can think of the pipeline inside them just like it’s a usual CPU consuming thread. At the same time, I/O threads are extremely cheap in comparison with CPU-bound threads, because, in fact, they are merely requests to devices
So with the first way, you are not utilizing the I/O threads but with the second you do, and it's much cheaper.
In your case, when accessing the Database, you are effectively doing an I/O (network) operation. By using asynchronous programming, you are awaiting on an I/O thread for the I/O (db read) operation to complete, without blocking a thread.
Another interesting read is async in depth
Throughout this entire process, a key takeaway is that no thread is dedicated to running the task. Although work is executed in some context (that is, the OS does have to pass data to a device driver and respond to an interrupt), there is no thread dedicated to waiting for data from the request to come back. This allows the system to handle a much larger volume of work rather than waiting for some I/O call to finish.
For even more information check the asynchronous overhead here
- If the async method completes synchronously the performance overhead is fairly small.
- If the async method completes synchronously the following memory overhead will occur: for async Task methods there is no overhead, for async Taskmethods the overhead is 88 bytes per operation (on x64 platform).
- ValueTask can remove the overhead mentioned above for async methods that complete synchronously.
- A ValueTask-based async method is a bit faster than a Task-based method if the method completes synchronously and a bit slower otherwise.
- A performance overhead of async methods that await non-completed task is way more substantial (~300 bytes per operation on x64 platform).
Upvotes: 1