简体   繁体   中英

Clarification needed on async and 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.

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

There are two kinds of tasks. Some Task s have code to execute, and they run on some thread. Other Task s 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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM