原文位址:Task 異步小技巧 - 一事冇誠 - 部落格園 (cnblogs.com)
async Task 文法糖出來後,異步程式設計變得非常簡單,适合需要耗費較長時間的任務。
有些小夥伴使用後可能會非常疑惑,使用異步和同步,在耗時上幾乎沒有差别。
下面我們看一個例子,場景是需要調用多個第三方的WebApi,分别是擷取名稱、年齡、性别,由于網絡環境等原因,api響應時間可能會接近1秒
1 public async Task Test()
2 {
3 var sw = new Stopwatch();
4 sw.Start();
5
6 var userName = await GetUserNameAsync();
7 var userAge = await GetUserAgeAsync();
8 var userSex = await GetUserSexAsync();
9
10 sw.Stop();
11 var ts = sw.Elapsed;
12 Console.WriteLine($"總共耗時:{ts.TotalMilliseconds}ms");
13 }
14
15 private async Task<string> GetUserNameAsync()
16 {
17 await Task.Delay(500);
18 return "小明";
19 }
20
21 private async Task<string> GetUserAgeAsync()
22 {
23 await Task.Delay(800);
24 return "11";
25 }
26
27 private async Task<string> GetUserSexAsync()
28 {
29 await Task.Delay(900);
30 return "11";
31 }
運作後發現,這個時間2秒多,這使用者體驗肯定是無法忍受的
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcukzMxEDMxQTO30iN1kTMzQDMwETNxATMxIDMy0iMzQzN5gTMvwFMxEjMwIzLcJzM0cTO4EzLcd2bsJ2Lc12bj5ycn9Gbi52YuAjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
導緻這樣結果的原因是每次進行異步調用的時候,都在異步函數前加上了 await ,這會導緻該線程阻塞,等待直到結果傳回,每個異步函數都await,時間自然就疊加了,為了解決這個問題,使用一個小技巧,可以将代碼改成下面這樣
1 public async Task Test()
2 {
3 var sw = new Stopwatch();
4 sw.Start();
5
6 var userNameTask = GetUserNameAsync();
7 var userAgeTask = GetUserAgeAsync();
8 var userSexTask = GetUserSexAsync();
9
10 var userName = await userNameTask;
11 var userAge = await userAgeTask;
12 var userSex = await userSexTask;
13
14 sw.Stop();
15 var ts = sw.Elapsed;
16 Console.WriteLine($"總共耗時:{ts.TotalMilliseconds}ms");
17 }
18
19 private async Task<string> GetUserNameAsync()
20 {
21 await Task.Delay(500);
22 return "小明";
23 }
24
25 private async Task<string> GetUserAgeAsync()
26 {
27 await Task.Delay(800);
28 return "11";
29 }
30
31 private async Task<string> GetUserSexAsync()
32 {
33 await Task.Delay(900);
34 return "11";
35 }
這次運作的總耗時,就是3個異步中,耗時最長那個 GetUserSexAsync
為什麼會這樣呢,這個小技巧的關鍵是這裡,當執行到異步函數的時候,不加 await,不進行等待,這樣就不會造成阻塞,讓這些任務乖乖在别的線程的執行,當需要用到他們的時候,再去等待傳回值,是以時間上不會進行疊加,哪個最長,總耗時就是哪個
1 var userNameTask = GetUserNameAsync();
2 var userAgeTask = GetUserAgeAsync();
3 var userSexTask = GetUserSexAsync();
4
5 var userName = await userNameTask;
6 var userAge = await userAgeTask;
7 var userSex = await userSexTask;
有不對、不好的地方請大佬們指正,我會改正過來,感謝各位大佬