1. 程式人生 > >c# async和await 用法(阻塞與不阻塞)

c# async和await 用法(阻塞與不阻塞)

read 底部 lba art paint 方法 完成後 圖片 網絡

看示例吧:

技術分享圖片
 1 void PagePaint()
 2 {
 3     Console.WriteLine("Paint Start");
 4     Paint();
 5     Console.WriteLine("Paint End");
 6 }
 7 
 8 void Paint()
 9 {
10     Rendering("Header");
11     Rendering(RequestBody());
12     Rendering("Footer");
13 }
14 
15 string RequestBody()
16 {
17     Thread.Sleep(1000);
18     return "Body";
19 }
技術分享圖片

假設有這麽個頁面布局的方法,依次對頭部、主體和底部進行渲染,頭部和底部是固定的內容,而主體需要額外請求。
這裏用Sleep模擬網絡延時,Rendering方法其實也就是對Console.WriteLine的簡單封裝而已。。。
PagePaint運行過後,結果是這樣的:

Paint Start
Header
Body
Footer
Paint End

挺正常的結果,但是Header渲染完以後頁面就阻塞了,這個時候用戶沒法對Header進行操作。
於是就進行這樣的修正:

技術分享圖片
 1 async void Paint()
 2 {
 3     Rendering("Header");
 4     Rendering(await RequestBody());
 5     Rendering("Footer");
 6 }
 7 
 8 async Task<string> RequestBody()
 9 {
10     return await Task.Run(() =>
11     {
12         Thread.Sleep(1000);
13         return "Body";
14     });
15 }
技術分享圖片

運行結果變成了這樣:

Paint Start
Header
Paint End
Body
Footer

這樣就能在Header出現之後不阻塞主線程了。

不過呢,Footer一直都得等到Body渲染完成後才能被渲染,這個邏輯現在看來還沒問題,因為底部要相對於主體進行布局。
然而我這時候又想給頁面加一個廣告,而且是fixed定位的那種,管啥頭部主體想蓋住就蓋住,你們在哪它不管。
比如這樣寫:

技術分享圖片
1 async void Paint()
2 {
3     Rendering(await RequestAds());
4     Rendering("Header");
5     Rendering(await RequestBody());
6     Rendering("Footer");
7 }
技術分享圖片

出現了很嚴重的問題,頭部都得等廣告加載好了才能渲染,這樣顯然是不對的。
所以應該改成這樣:

技術分享圖片
 1 async void Paint()
 2 {
 3     PaintAds();
 4     Rendering("Header");
 5     Rendering(await RequestBody());
 6     Rendering("Footer");
 7 }
 8 
 9 async void PaintAds()
10 {
11     string ads = await Task.Run(() =>
12     {
13         Thread.Sleep(1000);
14         return "Ads";
15     });
16     Rendering(ads);
17 }
技術分享圖片

這樣的運行結果就算令人滿意了:

技術分享圖片
Paint Start
Header
Paint End
Ads
Body
Footer
技術分享圖片

c# async和await 用法(阻塞與不阻塞)