Q:

"async await " how to understand it

the code is :
    static void Main(string[] args)
    {
        Test();

        Console.WriteLine("Main Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);

        Console.Read();
    }

    static async void Test()
    {
        Console.WriteLine("before wait Current Thread Id:{0}", Thread.CurrentThread.ManagedThreadId);

        await GetName();

        Console.WriteLine("after wait Current Thread Id:{0}", Thread.CurrentThread.ManagedThreadId);
    }

    static async Task GetName()
    {
        await Task.Run(() =>
          {
              Console.WriteLine("Current Thread Id :{0}", Thread.CurrentThread.ManagedThreadId);
              Console.WriteLine("In antoher thread.....");
          });
    }

the result is :
before wait Current Thread Id:9
Current Thread Id :10
In antoher thread.....
Main Thread Id :9       
after wait Current Thread Id:10  or  sometimes is  after wait Current Thread Id:11

i dont kown why  "Main Thread Id" is running fast than "after wait Current Thread Id".
and why has three ThreadID.

A:

Well, you can easily trace what happens.
For the main thread:

Method Test is called
before wait is printed out
A new task is queued on the threadpool, and Test immediately returns back to Main

Up to this point, this is a definite synchronous sequence. The remainder is not deterministic, because in theory, either the rest of Main or the threadpool Task can execute first - in fact, they can (in theory) also interleave, with Main Thread Id being printed out in between of Current thread Id and In another thread.
However, after wait will always be printed after In another thread.
You can already see that there's at least two threads involved - that shouldn't be surprising when you use Task.Run. So where does the third one come from? Well, await doesn't do any magic. There's no instruction for magic in IL. So what it actually does is just schedule a continuation on the Task you're awaiting, with the rest of the method. And since there's no synchronization context to marshal the continuation back on, the continuation will simply be queued to the thread pool again - taking another thread. However, in theory, the continuation may be allowed to run synchronously on the original thread (that is, the one used in Task.Run), although in this case I assume it's simply a reuse of the original thread, rather than synchronous continuation. But you can be entirely sure of one thing - it will never run on the main thread - not unless you explicitly setup a synchronization context and handle the marshalled tasks on the main thread instead of using Console.Read for the final blocking operation.

