Monster Hunter
Monster Hunter

Reputation: 866

Task await confusion

I have the following

async void A () {
  await B();
}

async Task B () {
  await Task.Factory.StratNew( ()=> C());
}

async Task C () {
  while (true) {
    //await Task.Factory.StartNew(()=> {Thread.Sleep(5000);});
    Thread.Sleep(5000);
  }
}

In the program above, A never returns because the while loop inside C. However if I uncomment the line inside C and KEEP Thread.Sleep(5000), A immediately returns. Could someone explain what is happening in there ?

Upvotes: 1

Views: 137

Answers (2)

Igor
Igor

Reputation: 62268

The main problem is thorouhly described in the article Task.Run vs Task.Factory.StartNew. If you were to change your code like this you would see what you were expecting I think.

async void A()
{
    await B(); 
}

async Task B()
{
    // await Task.Factory.StartNew(() => C());
    await Task.Run(async () => await C());
    // await Task.Run(() => C()); // this would still produce the same effect
}

async Task C()
{
    while (true)
    {
        await Task.Delay(5000);
        //Thread.Sleep(5000);
    }
}

See also this previous answer by Stephen Cleary. Essentially Task.Factory.StartNew does not respect the async/await model and you really should be using Task.Run with async/await code. Task.Factory.StartNew creates and starts a new Task without acually awaiting the results with the exception of when the Task returned is executed synchronously which happened when you removed the await inside of C.

Upvotes: 3

Riad Baghbanli
Riad Baghbanli

Reputation: 3319

When you have "await" inside you infinite loop, runtime interrupts infinite loop, yielding execution to outer calls, giving the chance to complete B (and consequently A) then it returns back to infinite loop.

Without the "await" there is no way B (and consequently A) can ever finish, they will "await" forever.

Upvotes: 2

Related Questions