Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly happens call async method without await keyword?

I have a web server and there is a periodic job merges and send records (lots of request logs).

Task.Run(() =>
{
    while (true)
    {
        try
        {
            MergeAndPutRecords();
        }
        catch (Exception ex)
        {
            Logger.Error(ex);
        }
    }
});

In MergeAndPutRecords function, there are code merging records and async function returns Task sending records. (Actaully it is Amazon Kinesis Firehose's PutRecordBatchAsync.)

Then what happens if i call that function without await keyword? Does function runs on seperated thread? Here says it is not. Then what is returning Task Means? Here says async method without await keyword means

  1. Starts the asynchronous method on the current thread. Ignores all results (including exceptions).

Then my periodic job and PutRecordBatchAsync are processed concurrently? I know asynchronouse and concurrent is different. But there is no await keyword and they are in same thread. Which one would be executed first? I'm confusing...

There would be massive records that needs to be merge and sent in real-time. So I think it must be executed concurrently..

like image 556
YB Yu Avatar asked Dec 22 '17 08:12

YB Yu


1 Answers

Then my periodic job and PutRecordBatchAsync are processed concurrently?

Using Task API you can ensure that they are executed concurrently (using Thread pool), but you need to understand the difference between in memory concurrent operations Vs IO based concurrency.

While In memory concurrency does benefit using Tasks, IO call once executed doesn't need thread at all, as it relies on hardware concurrency, if it ever use the thread, all that it would do it wait for the IO call to return, thus wasting the precious system resources and reducing system scalability

You case is that IO based concurrency, as you call a remote / network based API, how does async-await helps here ?

Well true Async operation will free up the thread context, on windows it would use IO completion port (queuing mechanism) to execute the Async call, while the calling thread is used to dispatch other similar calls, it would just need thread context on return of the IO call for serving the response and for that too, if its not a UI call, then use ConfigureAwait(false), so that any thread context can be used to deliver the response.

What if you don't use await with async ?

The call meant to be Asynchronous becomes Synchronous and would immediately impact the system scalability, as threads are now blocked, even worse for a long running IO operations. Have you seen how JavaScript frameworks always make a AJAX (Async) call to the server API, thus much more work is possible W/o blocking the Browser threads.

In general for In memory processing you would create certain number of Tasks and process them using Task.WaitAll or Parallel.ForEach for a collection, for Async processing, ideally recommendation is not to have a Task.Run anywhere, its preferred to have to Async from the entry point, like its possible in case of MVC, controllers can be async. Multiple calls are grouped together using Task.WhenAll representative Task and then awaited upon. even if you use Task.Run as in your code, then use async lambda to execute an asynchronous call

Summary :

Its mandatory to use await for asynchronous calls, else they async keyword is useless in that context and yes await will wait for the IO call to return before continuation is executed, though no thread is blocked in the process

like image 165
Mrinal Kamboj Avatar answered Nov 06 '22 23:11

Mrinal Kamboj