15.3 Task Task.Yield和Task.Delay說明
https://blog.csdn.net/hurrycxd/article/details/79827958
書上看到一個Task.Yield例子,Task.Yield方法建立一個立即返回的awaitable。等待一個Yield可以讓非同步方法在執行後續的部分時返回到呼叫方法。可以理解為離開當前的訊息佇列,回到佇列末尾,讓處理器有時間處理其他任務。
Yield方法在GUI程式設計中非常的有用,可以中斷大量的工作,讓其他任務使用處理器。看下面的程式碼:
1 static void Main(string[] args) 2 { 3 Task<int> value = FindSeriesSum(100000); 4 Console.WriteLine("主線其他任務開始"); 5 CountBig(10000); 6 CountBig(10001); 7 CountBig(10002); 8 Thread.Sleep(1000); 9 CountBig(10003); 10 Console.WriteLine("Length =" + value.Result); 11 Console.ReadKey();12 } 13 public static async Task<int> FindSeriesSum(int i1) 14 { 15 int sum = 0; 16 for (int i = 0; i < i1; i++) 17 { 18 sum += i1; 19 if (i % 20000 == 0) 20 { 21 awaitTask.Yield(); 22 Console.WriteLine("i % 20000 :i=" + i); 23 } 24 } 25 WebClient wc = new WebClient(); 26 Console.WriteLine("開始下載任務"); 27 string str = await wc.DownloadStringTaskAsync("https://www.baidu.com"); 28 return str.Length; 29 } 30 private static void CountBig(int p) 31 { 32 for (int i = 0; i < p; i++) 33 { 34 if (i == p - 1) 35 Console.WriteLine("p =" + p); 36 } 37 }
在執行下載任務await wc.DownloadStringTaskAsync("https://github.com/")前進行了大量的CPU運算,那麼執行緒會等到第一個await的時候才會非同步執行CountBig(10000);
程式執行的結果如下:
i % 20000 :i=0
i % 20000 :i=20000
i % 20000 :i=40000
i % 20000 :i=60000
i % 20000 :i=80000
開始下載任務
主線其他任務開始
p =10000
p =10001
p =10002
p =10003
Length =52728
我們需要立即返回的awaitable,讓程式執行其他的任務,去掉//await Task.Yield();前面的註釋符,得到的結果如下:
i % 20000 :i=0
主線其他任務開始
p =10000
i % 20000 :i=20000
p =10001
p =10002
i % 20000 :i=40000
i % 20000 :i=60000
i % 20000 :i=80000
開始下載任務
p =10003
Length =52728
可以看到現在開始下載任務之前就可以執行其他的任務了。最大條件的利用了資源。
Task.Delay方法建立一個Task物件,該物件暫停其線上程中的處理。
與Thread.Sleep()阻塞執行緒不同的是,Task.Delay不會阻塞執行緒,執行緒可以繼續處理其它的工作。
1 static void Main(string[] args) 2 { 3 Task<int> value = FindSeriesSum(100000); 4 Console.WriteLine("主線其他任務開始"); 5 CountBig(10000); 6 CountBig(10001); 7 CountBig(10002); 8 Thread.Sleep(1000); 9 CountBig(10003); 10 Console.WriteLine("Length =" + value.Result); 11 Console.ReadKey(); 12 } 13 public static async Task<int> FindSeriesSum(int i1) 14 { 15 await Task.Delay(1000); 16 WebClient wc = new WebClient(); 17 Console.WriteLine("開始下載任務"); 18 string str = await wc.DownloadStringTaskAsync("https://www.baidu.com"); 19 return str.Length; 20 } 21 private static void CountBig(int p) 22 { 23 for (int i = 0; i < p; i++) 24 { 25 if (i == p - 1) 26 Console.WriteLine("p =" + p); 27 } 28 }
主線其他任務開始
p =10000
p =10001
p =10002
開始下載任務
p =10003
Length =52728