Why do we need more than one await
statement in a C# method?
E.g. here we have three await
statements:
using System;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
namespace Acme.BookStore
{
public class BookStoreDataSeederContributor
: IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Book, Guid> _bookRepository;
public BookStoreDataSeederContributor(IRepository<Book, Guid> bookRepository)
{
_bookRepository = bookRepository;
}
public async Task SeedAsync(DataSeedContext context)
{
if (await _bookRepository.GetCountAsync() > 0)
{
return;
}
await _bookRepository.InsertAsync(
new Book
{
Name = "1984",
Type = BookType.Dystopia,
PublishDate = new DateTime(1949, 6, 8),
Price = 19.84f
}
);
await _bookRepository.InsertAsync(
new Book
{
Name = "The Hitchhiker's Guide to the Galaxy",
Type = BookType.ScienceFiction,
PublishDate = new DateTime(1995, 9, 27),
Price = 42.0f
}
);
}
}
}
In case we will remove the second and the third await
statements in the SeedAsync
no extra threads will be blocked, since already after the first await
we are not blocking any useful threads and we already allocated an extra thread for the first await
. So, by using the second and the third await
statements we are allocating the extra two threads.
Am I missing something here? Since abp.io
seems to be a big project I suspect that the examples would not be unreasonable and hence there is must be a reason to the use of the three await
statements instead of the one.
Why do we need more than one await statement in a C# method?
You need as much await in your code, you want to (a)wait for the execution of the called async method completes. When you call an asynchronous method, it will (at some point!) return a task (incomplete or completed one), what is technically a promise from that method that at some point it will completes its job.
For example _bookRepository.InsertAsync(...)
promise that it will insert the item into the repository and it will notify you via the returned Task when it is happened. It is now up to you, the caller, whether you want to wait for it using await, or you do not care if and when this job finished (fire and forget) so you do not use await, and continue to execute the rest of the caller code.
So it is totally valid to remove the await keywords almost everywhere but there is a very high chance it will alter the program flow and could lead to side effects (explanation in the next section).
In case we will remove the second and the third await statements in the SeedAsync no extra threads will be blocked, since already after the first await we are not blocking any useful threads and we already allocated an extra thread for the first await. So, by using the second and the third await statements we are allocating the extra two threads.
There are several misunderstanding here:
there is must be a reason to the use of the three await statements instead of the one.
Without any further investigation into the project you quoted, most probably _bookRepository.InsertAsync(...)
methods are not "parallel safe", otherwise await Task.WhenAll(insert1, insert2)
format could have been used. Also not using await for the insertions potentially lead to side effect, for example multi threading like race conditions (read state before write has been finished).
EDIT: You can find lots of useful reading material on docs.microsoft.com, such this: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/task-asynchronous-programming-model
I suggest to read them multiple times and make test apps because the topic is more complex than it looks like and filled with small details easy to misinterpret.
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