andrew slaughter
andrew slaughter

Reputation: 1117

Should I use async/await in my controller?

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

Answers (1)

Athanasios Kataras
Athanasios Kataras

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.

Edit (After Liam's comment)

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

  1. If the async method completes synchronously the performance overhead is fairly small.
  2. 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).
  3. ValueTask can remove the overhead mentioned above for async methods that complete synchronously.
  4. A ValueTask-based async method is a bit faster than a Task-based method if the method completes synchronously and a bit slower otherwise.
  5. A performance overhead of async methods that await non-completed task is way more substantial (~300 bytes per operation on x64 platform).

Upvotes: 1

Related Questions