async/await执行顺序
测试后的理解,碰见Task.Run开始执行子线程,如果Task.Run存在await关键字(如果是Task方法函数,有无await主线程都会执行里面的,直到执行到Task.Run为止),
则主程序执行至这个Task.Run的await后会跳出去执行主线程原有的内容,await后面的内容会在子线程表结束后继续后面主线程未执行完的内容。
如果加了async但是没有用到await,但是又用到了Task的返回值,如Task.Result,则主线程会等待子线程完成后才继续执行。
await相当于线程跳出的点,在没碰到Task.Run(开启线程)并且await之前会继续执行,但是碰到后,会逐个根据Task跳出。
如:
static void Main(string[] args) { //task->async异步方法和await,主线程碰到await时会立即返回,继续以非阻塞形式执行主线程下面的逻辑 Console.WriteLine("---------------------------------"); Console.WriteLine("①1我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId); var testResult = TestAsync(); Console.WriteLine("2我是主线程,线程ID:{0}", Thread.CurrentThread.ManagedThreadId); Console.ReadKey(); }
static async Task TestAsync() { Console.WriteLine("②调用GetReturnResult()之前,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss")); var name = InTask();//1主线程进入方法。3主线程跳出InTask()后继续执行。(假如下面6的await在这里,那么4也是又1.1完成) // name; Console.WriteLine("④调用GetReturnResult()之后,线程ID:{0}。当前时间:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("yyyy-MM-dd hh:MM:ss")); Console.WriteLine("⑥得到GetReturnResult()方法的结果一:{0}。当前时间:{1}", await name,//4碰到await主线程跳出此方法,执行TestAsync()外的逻辑 Thread.CurrentThread.ManagedThreadId);//这里由1.1来完成 Console.WriteLine("⑥得到GetReturnResult()方法的结果二:{0}。当前时间:{1}", name, //这里也是由1.1来完成 Thread.CurrentThread.ManagedThreadId); } static async Task<string> InTask() { Console.WriteLine("InTask执行Task.Run之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId); var w = await Task.Run(GetReturnResult3);//2.主线程碰到开启子线程方法,并且有await,跳出方法,执行方法外部逻辑。 Console.WriteLine("InTask执行Task.Run后, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId);//这里由1.1开始继续完成 return w; } static async Task<string> GetReturnResult3() { Thread.Sleep(20);//子线程1开始 Console.WriteLine("③执行Task.Run之前, 线程ID:{0}", Thread.CurrentThread.ManagedThreadId); var a = Task.Run(() => //子线程的子线程,叫1.1。开始 { Thread.Sleep(2000); Console.WriteLine("⑤GetReturnResult()方法里面线程ID: {0}", Thread.CurrentThread.ManagedThreadId); return "我是返回值";//1.1 因为他是嵌套的最后一层,所以它并没有结束,而是跳出去,执行主线程没有完成的部分。 }); Thread.Sleep(20); Console.WriteLine("③.1执行Task.Run后, 线程ID:22{0}", Thread.CurrentThread.ManagedThreadId);//理论这里应该是子线程1完成,因为程序在这里执行完后才开始等待2秒的,
//那么应该是由子线程1完成的才对,但是线程ID和子线程ID完全不一样。也不是1.1线程。不知道为什么
return await a;//子线程1跳出。这里子线程已经结束了 }
所有主线程跳出的方法后面的内容都由子线程完成,套了多个Task.Run的情况下,只完成当前线程内的,由套在里面的子线程完成主线程剩下的部分。

浙公网安备 33010602011771号