There is no direct relationships between Task and Thread. Task-await-async is a mere simplified form of Asynchronous-task + EventHandler. (Related concepts: Events, Delegates, Lambda expressions).
For example, though we are quite casually using flat code as follows these days,
async {
Debug.WriteLine("Before");
await Task.Delay(100);
Debug.WriteLine("After");
:
Debug.WriteLine("The End");
}
Once upon a time (maybe in .NET3.x or early .NET4.x era, see C# Version History), there were no await-async syntax. There was only AsynchronousDelayTaskWorker class or something which (1) takes event handler, (2) runs time-consuming task asynchronously and then (3) fires the event in the end. To use such apparatus, programmers had to write complex structured code as follows.
{
Debug.WriteLine("Before");
var worker = new AsynchronousDelayTaskWorker();
worker.SetCompletedEventHandler(new CompletedEventHander(()=>
{
// Whether this handler is dispatched on the original thread or not
// depends on worker's implementation.
Debug.WriteLine("After");
:
Debug.WriteLine("The End");
}));
worker.RunAsync();
}
But after task-async-await were introduced in .NET4.5, it became possible to write such a code in a flat and clean manner as follows.
async {
Debug.WriteLine("Before");
await Task.Delay(100);
// Following codes are actually placed in event handler.
Debug.WriteLine("After");
:
Debug.WriteLine("The End");
}
—— And C# programmers lived happily ever after.
Using task without await is nearly equivalent to running the legacy asynchronous task without registering event handler. The task runs asynchronously somewhere (in many cases in background thread). It's not possible to run another code after the task completes because it's unknown when the task finishes/finished, without event handler.
Since the task is mere object which doesn't interfere with subsequent codes, all the lines run straightforwardly.
{
Debug.WriteLine("Before");
// The following worker runs somewhere
// as the raw Task.Delay(100) does.
var worker = new AsynchronousDelayTaskWorker();
worker.RunAsync();
// Following codes run immediately.
Debug.WriteLine("After");
:
Debug.WriteLine("The End");
}