今天要记录的内容摘要是:
什么时候异步代码能“等”在那里,什么时候不会“等”
这两天Coding的时候碰到一个事儿,就是想让异步等在那里结果却直接执行过去了,比如这样:
1 async static void Count() 2 { 3 Console.WriteLine("Task Void 开始"); 4 Console.WriteLine(Thread.CurrentThread.ManagedThreadId); 5 int count = 0; 6 while (count < 10) 7 { 8 Console.WriteLine("Print value:{0}", count); 9 count++; 10 await Task.Delay(500); 11 } 12 Console.WriteLine("Task Void 结束"); 13 }
接下来写这两句:
1 var taskVoid = new Task(Count); 2 await taskVoid;
哈哈,原本按照其它异步方式去写的时候比如 await HttpClient.GetAsync(); 是非常正常的,程序的逻辑会停在这一句,直到获得结果才会进行下面的语句。但运行 await taskVoid 后,会立即运行下面的语句,这是怎么回事?经过仔细检查发现是因为 Count 方法没有返回值,是 void ,因此必须要加以改造。如果 Count 方法返回值是 Task ,await 才能起效,比如改成这样:
1 static void Main(string[] args) 2 { 3 Entry(); 4 Console.ReadLine(); 5 6 } 7 8 async static Task CountAsync() 9 { 10 Console.WriteLine("Task Void 开始"); 11 int count = 0; 12 while (count < 10) 13 { 14 Console.WriteLine("Print value:{0}", count); 15 count++; 16 await Task.Delay(500); 17 } 18 Console.WriteLine("Task Void 结束"); 19 } 20 21 async static void Entry() 22 { 23 // 创建一个无参数无返回值的方法 24 var taskVoid = Task.Factory.StartNew(CountAsync); 25 26 await taskVoid.Result; 27 // 创建一个 taskVoid 之后才能运行的方法 28 var taskContinue = taskVoid.ContinueWith(async (t) => 29 { 30 31 Console.WriteLine("这是在 TaskVoid 运行之后才能运行的 TaskContinue,Task void 的状态是 {0}", t.Status); 32 await Task.Delay(1000); 33 }); 34 ; 35 }