Once the main thread hits await Task.Delay(1000); it won't "move on" to the next iteration of the while loop
Yes, it will.
Remember, Task.Delay is not Thread.Sleep. Sleep shuts down your thread and doesn't return until it's awake again. Task.Delay immediately returns a task which represents a delay.
So can you explain how this unblocks?
await
has the following behaviour:
- Check the task to see if it is completed. If yes, and it completed with an exception, throw the exception. If yes, and it completed normally, produce the value, if any, and continue executing normally.
- The task is not completed. Make a delegate whose action is to start running this method again at the point of the await. (This is the tricky bit for the compiler to do; see any article on the details of the await codegen for an explanation.) Sign up that delegate as the continuation of the task, and return to your caller.
- If this is the first await encountered in the method, the thing that is returned is a task representing the workflow of the method, so that the caller can in turn await it.
public async Task WaitOneSecondAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done waiting 1 second!");
}
has these pseudocode semantics:
Task thisTask = a new task;
Action completion = () => {
Console.WriteLine("Done...");
mark thisTask as complete
};
Task delayTask = Task.Delay(1000);
if (delayTask has already completed normally)
{
completion();
return thisTask; // Return a completed task.
}
else if (delayTask completed with an exception)
throw the exception
else
assign completion as the completion of delayTask
return thisTask;
See how that works? If the delay is not already complete then the method signs up a delegate as the completion of the delay and returns to the caller. If the caller is the message loop, then the message loop gets to run again.
What happens when the delay completes? It queues up a message that says to call its completion, and the completion runs at some point in the future.
Of course the real codegen is much, much more complicated than the little pseudocode I've shown here; that's just to get the idea across. The real codegen is complicated by the fact that exception handling is more difficult than just throwing the exception, and by a variety of optimizations that delay generating objects on the heap when possible.