Sandip Agrawal
Sandip Agrawal

Reputation: 45

Is Async await Actually a blocking call?

private async Task<string> GetStateInfo()
{
   var cityId = await GetCityIdByNameAsync("Delhi");
   var state = await GetStateNameAsync(cityId);
   return state;
}

As we know async and await are used for asynchronous programing and they are for non-blocking programming model. But in the code above the var state = await GetStateNameAsync(cityId); executes when the 1st line executes as it takes input from that. So I dont understand is it a blocking call or non-blocking call?

Upvotes: 4

Views: 1797

Answers (2)

yuv
yuv

Reputation: 594

There are 2 basic topics/questions that should be covered. I think we always miss discussing the second topic of using await.

  1. Why we should use asynchronous programming?
  2. If we are using asynchronous programming to make the thread non-blocking then why we are using the await keyword to make the thread awaited?

Let me discuss these 2 topics with an example. Technical details will be kept aside for now.

Why Asynchronous Programming?

Let's say we have one method CreateSale

public void CreateSale(int saleId, int customerId)
{
    var transactionId = AddTransactionToPaymentGateway(saleId, customerId);
    SaveSaleToLedger(transactionId, customerId);
}

Now, assume that at the same moment, there are 2 users that initiate the CreateSale operation. In a synchronous way, the thread starts to execute the operations like the below,

1. User:1 → AddTransactionToPaymentGateway
-- Wait until the job is done. --

2. User:1 → SaveSaleToLedger
-- Wait until the job is done. --

3. User:2 → AddTransactionToPaymentGateway
-- Wait until the job is done. --

4. User:2 → SaveSaleToLedger
-- Wait until the job is done. --

In the synchronous method, the thread will wait for each operation to be done before starting the next one. Also, notice that in this waiting period, the thread remains fully idle. The operations are DB intensive (let's say) and the thread just waits and does nothing. This will make the user2 wait unnecessarily to start his operation whereas the thread remains idle.

In asynchronous programming, we do not block the thread idly. Rather it should start executing the next operations.

public async Task CreateSaleAsync(int saleId, int customerId)
{
    var transactionId = AddTransactionToPaymentGatewayAsync(saleId, customerId);
    SaveSaleToLedgerAsync(transactionId, customerId);
}
1. User:1 → AddTransactionToPaymentGatewayAsync
2. User:1 → SaveSaleToLedgerAsync
3. User:2 → AddTransactionToPaymentGatewayAsync
4. User:2 → SaveSaleToLedgerAsync

Now the thread is not waiting for any of the jobs done.
And here is the answer to the first topic.

Why await?

In the async version of the code, the thread is not waiting for any of the jobs to be done. But this approach will create another issue.
Look, as it is not waiting for the first job of the User1 but rather starting the second job of the same user, this will break the application. Because we do not get any transactionId yet to start the second job.
To overcome the issue, here comes the savior await.

With await we are telling the thread that okay, you are good to do your tasks asynchronously but not mine!! You should wait for my tasks to be done to execute the next. But in the meantime, you are free to serve other users.

public async Task CreateSaleAsync(int saleId, int customerId)
{
    var transactionId = await AddTransactionToPaymentGatewayAsync(saleId, customerId);
    await SaveSaleToLedgerAsync(transactionId, customerId);
}
1. User:1 → AddTransactionToPaymentGatewayAsync
2. User:2 → AddTransactionToPaymentGatewayAsync
3. User:1 → SaveSaleToLedgerAsync   //start after task 1 is done
4. User:2 → SaveSaleToLedgerAsync   //start after task 2 is done

Look how the thread is starting the User2's tasks before User1's SaveSaleToLedgerAsync task.
It also remembers that the User1 has a job running. And whenever the job is done it will start the 2nd task of the user. But in the meantime, it will serve other users' tasks.
This is the job of the keyword await. Again, the await does not block other user's tasks. It is still asynchronous. It just waits for the current user's task.
Hope this explains well.

Upvotes: 4

Stephen Cleary
Stephen Cleary

Reputation: 456507

Please see my async intro. await is an "asynchronous wait", so it "pauses" the method and returns an incomplete Task<string> instance. So the method is waiting for the task returned by GetCityIdByNameAsync to complete, but there is no thread blocked waiting for it.

Upvotes: 6

Related Questions