C
C#3y ago
palapapa

Understanding await control flow [Answered]

According to my understanding, when the control flow reaches an await, it would return immediately to the call site. But what would happen if the method you are currently awaiting awaits another method? Let's say I have 3 methods: Main, AsyncMethod1, and AsyncMethod2. If I call AsyncMethod1 in Main, the control flow would immediately return to Main as far as I know. Then, inside AsyncMethod1, it awaits AsyncMethod2. In that case, would the control flow return to AsyncMethod1? But that wouldn't make much sense because AsyncMethod1 is already awaiting something so it cannot continue. Which part of my understanding is wrong? By the way, if I have an async Main, where would the control flow return to when I await in Main? Does it simply not return?
19 Replies
333fred
333fred3y ago
You're misunderstanding await here. Let's put some real code here to make talking about it easier
async Task Main()
{
await M1();
}

async Task M1()
{
await M2();
}

async Task M2()
{
await Task.Sleep(Timespan.FromSeconds(1));
}
async Task Main()
{
await M1();
}

async Task M1()
{
await M2();
}

async Task M2()
{
await Task.Sleep(Timespan.FromSeconds(1));
}
When you say await, you're saying "I would like this method to resume after the Task that is returned from the method that I'm calling has completed" And you return a task yourself, so the caller has ability to call you, and then ignore that task for a while, and then eventually check to see if it has completed But by doing await, you are signaling "Hey, don't resume me until the thing I awaited is done" Let's rewrite the above code a bit (the real lowering is much more complicated than this, but this is a good example):
palapapa
palapapaOP3y ago
Can I understand it as "await will return to the call site immediately if and only if the caller did not await this call"?
333fred
333fred3y ago
void CompilerGeneratedMain()
{
Main().GetAwaiter().GetResult(); // Synchronously wait for Main to finish
}

Task Main()
{
return M1().ContinueWith(() => Console.WriteLine("Main"));
}

Task M1()
{
return M2().ContinueWith(() => Console.WriteLine("M1"));
}

Task M2()
{
return Task.Sleep(Timespan.FromSeconds(1)).ContinueWith(() => Console.WriteLine("M2"));
}
void CompilerGeneratedMain()
{
Main().GetAwaiter().GetResult(); // Synchronously wait for Main to finish
}

Task Main()
{
return M1().ContinueWith(() => Console.WriteLine("Main"));
}

Task M1()
{
return M2().ContinueWith(() => Console.WriteLine("M1"));
}

Task M2()
{
return Task.Sleep(Timespan.FromSeconds(1)).ContinueWith(() => Console.WriteLine("M2"));
}
No
palapapa
palapapaOP3y ago
So does the control flow "return immediately" at all?
333fred
333fred3y ago
Ish Let's just take M2 It calls Task.Sleep() (which returns a task), schedules a continuation after it, and returns that task Now, to be clear, this isn't precisely how it works. The actual generated code is a good deal more complicated
palapapa
palapapaOP3y ago
From this example, I understood it as "await will only continue after the thing it's awaiting and everything that that thing awaits and so on all completes"
333fred
333fred3y ago
Right, that's the effect All the code knows, though, is that its waiting for that one thing And however long it takes for those to finish is however long it takes
palapapa
palapapaOP3y ago
So if I call an async method in a non-async method, is the only way to retrive the return value to block the thread and wait?
333fred
333fred3y ago
Correct That's why async is considered "viral"
palapapa
palapapaOP3y ago
So when I await something, will the current thread return to the thread pool and be ready to do anything that the OS wants it to do, instead of blocking and do nothing?
333fred
333fred3y ago
Maybe Depends on whether the thing you await actually defers work and yields the thread It's possible it completes synchronously
palapapa
palapapaOP3y ago
But in the case where it's done multithreadedly, that's what happens right?
333fred
333fred3y ago
Uh... mulithreadedly isn't an adequate description for me to answer
palapapa
palapapaOP3y ago
What do you mean? Or should I say asynchronously?
333fred
333fred3y ago
I mean that "mulithreadedly" isn't a description of anything It's not even a word Asynchronously is also not a description of anything
palapapa
palapapaOP3y ago
Thank you, I got it !solved
333fred
333fred3y ago
$close
MODiX
MODiX3y ago
Use the /close command to mark a forum thread as answered
Accord
Accord3y ago
✅ This post has been marked as answered!

Did you find this page helpful?