Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clarification needed on async and await

Tags:

c#

async-await

I read many articles on async and await(mostly from msdn - which is good actually). There is still one question that bothers me and I could not find the answer.

If there is an await statement on a task then the control is returned to its caller until it is awaited again in the caller. In that case is this time consuming task getting executed in a separate thread? If not then how is it getting executed parallel to the main thread.

async Task<string> GetContentsAsync()
{
    int sample = 0;
    HttpClient client = new HttpClient();
    Task<string> contents = client.GetStringAsync("http://www.microsoft.com");
            
    string data = await contents;
    return data;
}

I hope my question is clear.

like image 203
ckv Avatar asked Dec 22 '25 05:12

ckv


2 Answers

In that case is this time consuming task getting executed in a separate thread?

There are two kinds of tasks. Some Tasks have code to execute, and they run on some thread. Other Tasks do not execute code; they just represent some future event.

The "event tasks" are used a lot by async, particularly in I/O scenarios. In your example, you're executing an HTTP GET. GetStringAsync will send the HTTP request and then return an "event task" that completes when the response is received. While the HTTP request is in flight and being processed by the server, there's no code for the client to execute for that request. So there's no thread required, and none is used.

Also see my answer here.

like image 164
Stephen Cleary Avatar answered Dec 23 '25 20:12

Stephen Cleary


It depends on how the task is created, but no, tasks are not inherently executed on a separate thread automatically. Some helper methods, like Task.Run for example, can help you make sure a task is put on a separate thread (the thread pool in this case).

Remember that a GUI application, let's say WinForms specifically, runs a so-called event loop. In WinForms this happens behind your back, in the Application.Run call. This event loop receives events like clicks and invokes your handlers. The thread that this loop executes on is referred to as "the GUI thread". In WinForms, it's the thread that creates all the controls, and hence also the only thread allowed to touch those controls.

When you create a task using the async modifier on a method, that code is also scheduled to execute via this event loop. It's just queued up. Just like the good old Invoke calls. So once your event handler returns, eventually the event loop gets to that queued up task, executes it, and then executes the rest of the method that followed the await. No parallelism here.

However, there are other ways to create tasks; calling an async method is just one way. Task.Run creates tasks that are put on separate threads. GetStringAsync you show in your example will actually run in parallel with whichever thread invoked the task.

like image 29
Roman Starkov Avatar answered Dec 23 '25 20:12

Roman Starkov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!