The following program executes both WriteLine
s, even though the task is never awaited:
var nonAwaitedTask = Foo();
Thread.Sleep(10);
static async Task Foo()
{
Console.WriteLine("before delay");
await Task.Delay(1);
Console.WriteLine("after delay");
}
When removing Thread.Sleep
the second WriteLine
is not executed.
Is this a race condition even though only the main thread should be involved? When and why does the (main) thread continue execution of the async
code (MoveNext
)?
I could see multiple scenarios where the WriteLine
could be executed, e.g.:
- if
await Task.Delay(0)
was used (awaiter.IsCompleted
is immediatelytrue
andFoo
would not yield). - if
await Task.Delay(1).ConfigureAwait(false)
was used (a different thread could run the code while the main thread is blocking onThread.Sleep
) - if we
await
(e.g. aTask.Delay(10)
) inMain
(instead of blocking onThread.Sleep
) which would allowFoo
to run concurrently.
I understand that the latter two would be race-conditions and that the first compiler optimisation might not be guaranteed (in short, just await
your tasks).
However, my mental model where only one thread is involved and where this thread could only continue execution on well defined (await
) points does not seem to hold.
Any explanations are highly appreciated!