Does omitting await keyword once in the call stack break the asynchronous behavior of the whole stack?
https://softwareengineering.stackexchange.com/questions/331353
-
28-12-2020 - |
Вопрос
Call stack may contain several methods returning Task
. If all of them are decorated with async
, the flow of execution is quite simple. However, what if one of them is not await
ed - are other method calls from that method executed asynchronously or not?
Here's an example:
If I have
async Task A()
{
...
await B();
...
}
and if I call A();
and not await (A);
- will await B();
be awaited?
Решение
In .net the async await
keywords are an extension of the Task Parallel Library. When you do not await
an async
method it is almost equivalent to calling Task.Run(()=>A())
(There are some gotchas regarding UI threads or other single threaded applications here as with out .ConfigureAwait(false)
, when creating the task, the awaited code will try to pick up on the same thread context. If you are awaiting from a background worker thread context then await and Task.Run()
are running in the same context. If you are on the UI thread then the context of Task.Run()
and the awaited context are different.)
In your example A() would start, return control at await B()
and then the code calling A()
would continue while A()
was waiting for B()
to complete.
A simple example would be the following:
static void Main(string[] args)
{
Console.WriteLine("Starting main");
A();
Console.WriteLine("Finished Main");
//dont end before A() finishes.
Console.ReadLine();
}
static async Task A()
{
Console.WriteLine("starting A");
await B();
Console.WriteLine("Finishing a");
}
static async Task B()
{
//Add a delay before the Console.WriteLine
await Task.Delay(1000);
Console.WriteLine("starting B");
await Task.Delay(1000);
Console.WriteLine("Finishing b");
}
When the main method calls A()
execution is serial until the await B()
. After A()
calls await, control is returned to main which then finishes. At this point A()
is still out there running "Fire and Forget", which is bad in the case of a console program so we need to make sure that the main thread does not complete before A()
finishes. If we don't have the Console.ReadLine();
the program will end after the call to await
in A()
.