5

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 awaited - 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?

4

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().

  • I'm not entirely sure this is accurate. I could have sworn that you only get fire and forget behavior with async void. For tasks that aren't awaited, aren't they simply run synchronously? (Please, I could be wrong, someone correct me if I am.) – RubberDuck Sep 18 '16 at 15:33
  • @RubberDuck You get fire and forget from any non awaited task. When you spin off multiple async methods you can then call await on Task.WhenAll to wait for all of them to finish (IE: Downloading multiple independent files in parallel). If there is no await, then the files will still download but nothing will wait on them. async void is a special case where you CAN NOT await but nothing says you have to await a method returning a task. – RubberChickenLeader Sep 18 '16 at 15:41
  • Okay. Yeah @WindRaven, it looks like you're right about that. msdn.microsoft.com/en-us/library/hh965065.aspx – RubberDuck Sep 18 '16 at 15:53
  • 6
    'Task.Run(()=>A())' isn't completely accurate. Task.Run runs the task on a separate thread, whereas just firing A() and forgetting about it, still runs it on the main thread. This can be a pretty important factor in cases where the UI does something after a task reaches a specific point in code. Arguably this is a design flaw, if your code relies on other code you can't await. But regardless, this could be a problem – Falgantil Sep 21 '16 at 13:20
  • 1
    Omitting await is certainly not equivalent to Task.Run(...). The latter uses a separate thread. "Do not try and use a thread. That's unnecessary. Instead, only try to realize the truth... There is no thread." Ah, I'll let Stephen Cleary explain it: blog.stephencleary.com/2013/11/there-is-no-thread.html – Timo Nov 5 '18 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.