Help on how async/await works
Hi everyone, I am currently learning about asynchronous programming in c# and have been reading the documentation at https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/. I understand how the usage of await will pause execution until the task completes, but I dont fully understand where execution goes after hitting an await statement. The documentation mentions
The await keyword is where the magic happens. It yields control to the caller of the method that performed await, and it ultimately allows a UI to be responsive or a service to be elastic.
What exactly does it mean by the caller of the method that performed await, is it talking about the method that called the method that performed await, or something else?Asynchronous programming - C#
An overview of the C# language support for asynchronous programming using async, await, Task, and Task
8 Replies
it goes nowhere, the task just does nothing until the await is done
$nothread
There Is No Thread
This is an essential truth of async in its purest form: There is no thread.
or are you asking more about where execution resumes after the await is done?
Im asking more about what exactly it means by yielding control somewhere else
the article i linked explains it
That makes sense, I have another question - A lot of the examples online mention using asynchronous code to not block a UI thread while doing some long running operation, by UI thread does it mean: One specific thread which is always doing the UI work, or that by using asynchronous code there will only ever be one thread which is doing UI work?
the first one
at least that's how it's typically implemented in the UI frameworks i've used
So, 'async' turns a method into something magical. A state machine. That is organized so that different parts of the method can be invoked independently. What actually happens when await happens is 'control is returned', which literally means the method returns to it's caller. But it returns a Task. That Task can later be used to resume execution of the rest of the method.
When you call Foo the first line runs. The second line runs, calling OtherThing, which returns a Task. Because you are awaiting that Task, a new Task is created that is linked to the Task that returns from OtherThing. That new task is set up to, upon completion, jump back into line 3. Whenever that happens, the new task has it's result set to i, and is marked completed, so the caller of Foo then has a Task that will eventually return 1, but only after it's bneen resumed by the first task returned by OtherThing.