0

I have the following code

class Program
{
    public  async  Task<bool> StartMyTask()
    {
        await Foo();

        return true;

    }

    public async Task<bool> Foo()
    {

        for (int i = 0; i < 1000000; i++)
        {
            Console.WriteLine("Loop");
        }
        return true;

    }


    static void Main(string[] args)
    {
        Program obj = new Program();

        var myTask = obj.StartMyTask();     
        Console.WriteLine("Before Task Return");                                    


        Console.ReadLine();
    }
}

According to my understanding when "await Foo()" gets called, a thread will be created which will execute the "Foo()" method and the control would be returned back to the caller (Main method).

By considering this, "Before Task Return" should be printed before the "Foo()" method completes. But its not happening, first the "Foo()" method completes and then "Before Task Return" is displayed.

Hien Nguyen
  • 24,551
  • 7
  • 52
  • 62
Waleed Naveed
  • 2,293
  • 2
  • 29
  • 57
  • 9
    Your understanding is wrong, no thread is created for `Foo`, and since it doesn't actually do any asynchronous work, it will block until the loop is done. – Lasse V. Karlsen Jun 14 '19 at 11:42
  • 2
    In short async methods those doesn't do any truly async work works the same as not async. – Sat Jun 14 '19 at 11:45
  • I am using await with "Foo()" in "StartMyTask" method. Shouldn't it wait for Foo to complete and return the control back to Main method ? @LasseVågsætherKarlsen – Waleed Naveed Jun 14 '19 at 11:46
  • Yes it should, doesn't it do that? Your question seems to indicate it does, it completes the entire call to `StartMyTask`, including the entire loop, before `"Before Task return"` gets printed. – Lasse V. Karlsen Jun 14 '19 at 11:47
  • No. If its doing that then "Before Task Return" should be printed before the Foo execution , but its not doing that @LasseVågsætherKarlsen – Waleed Naveed Jun 14 '19 at 11:48
  • Correct, it is, as you said, waiting for `Foo` to complete before it returns control back to the Main method. Please go through what you're saying and be specific. – Lasse V. Karlsen Jun 14 '19 at 11:49
  • yes, shouldn't "Before Task return" be printed before the complete Foo execution ? @LasseVågsætherKarlsen – Waleed Naveed Jun 14 '19 at 11:49
  • 5
    No, not the way you've written your code. As I said, your understanding of async/await is wrong. Neither of those two keywords create new threads. Since you're not *actually* doing asynchronous work here, your code is behaving exactly as it would if you removed async/await keywords and did everything synchronously. – Lasse V. Karlsen Jun 14 '19 at 11:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/194941/discussion-between-lasse-vagsaether-karlsen-and-waleed-naveed). – Lasse V. Karlsen Jun 14 '19 at 11:51
  • 3
    Since your Async is not awaiting anything, it will run synchronously. You should get a warning in the compiler to this effect. – theMayer Jun 14 '19 at 11:51
  • StartMyTask is awaiting at Foo @theMayer – Waleed Naveed Jun 14 '19 at 11:58
  • If your write following in your StartMytask method : `await Task.Delay(100); await Foo();` you will get output you want :) – Maksim Simkin Jun 14 '19 at 12:01
  • 4
    short version: async != threads (they are related topics, but **not the same**) – Marc Gravell Jun 14 '19 at 12:03

2 Answers2

6

According to my understanding when "await Foo()" gets called, a thread will be created which will execute the "Foo()" method and the control would be returned back to the caller (Main method).

No, absolutely not. async and await do not create threads on their own. async allows you to use await, and await will "asynchronously wait" - i.e., pause the method, return, and then resume the method when its operation completes.

Note that the compiler is giving you a warning that you have a method marked async but it will run synchronously. So the compiler is already telling you exactly what's wrong.

If you want to use a background thread, you can use Task.Run to call the synchronous Foo method:

public async Task<bool> StartMyTask()
{
  await Task.Run(() => Foo());
  return true;
}

public bool Foo()
{
  for (int i = 0; i < 1000000; i++)
  {
    Console.WriteLine("Loop");
  }
  return true;
}
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
-1

Since your Foo method creates no task then your code wont diverge as you expect, but making it as follows resolves your concerns:

public async Task<bool> Foo()
    {
       return await Task.Run(() =>
       {
           for (int i = 0; i < 100000; i++)
           {
               Console.WriteLine("Loop");
           }
           return true;
       });
    }
muaz
  • 550
  • 9
  • 15