void PagePaint() { Console.WriteLine("Paint Start"); Paint(); Console.WriteLine("Paint End"); } void Paint() { Rendering("Header"); Rendering(RequestBody()); Rendering("Footer"); } string RequestBody() { Thread.Sleep(1000); return "Body"; }
假設有這麼個頁面佈局的方法,依次對頭部、主體和底部進行渲染,頭部和底部是固定的內容,而主體須要額外請求。
這裏用Sleep模擬網絡延時,Rendering方法其實也就是對Console.WriteLine的簡單封裝而已。。。
PagePaint運行事後,結果是這樣的:網絡
Paint Start
Header
Body
Footer
Paint End
挺正常的結果,可是Header渲染完之後頁面就阻塞了,這個時候用戶無法對Header進行操做。
因而就進行這樣的修正:異步
async void Paint() { Rendering("Header"); Rendering(await RequestBody()); Rendering("Footer"); } async Task<string> RequestBody() { return await Task.Run(() => { Thread.Sleep(1000); return "Body"; }); }
運行結果變成了這樣:async
Paint Start
Header
Paint End
Body
Footer
這樣就能在Header出現以後不阻塞主線程了。
不過呢,Footer一直都得等到Body渲染完成後才能被渲染,這個邏輯如今看來還沒問題,由於底部要相對於主體進行佈局。
然而我這時候又想給頁面加一個廣告,並且是fixed定位的那種,管啥頭部主體想蓋住就蓋住,大家在哪它無論。
好比這樣寫:佈局
async void Paint() { Rendering(await RequestAds()); Rendering("Header"); Rendering(await RequestBody()); Rendering("Footer"); }
出現了很嚴重的問題,頭部都得等廣告加載好了才能渲染,這樣顯然是不對的。
因此應該改爲這樣:測試
async void Paint() { PaintAds(); Rendering("Header"); Rendering(await RequestBody()); Rendering("Footer"); } async void PaintAds() { string ads = await Task.Run(() => { Thread.Sleep(1000); return "Ads"; }); Rendering(ads); }
這樣的運行結果就算使人滿意了:spa
Paint Start
Header
Paint End
Ads
Body
Footer
總結:線程
1.Paint()加async表示是可異步的,當裏面有awit的時候,調用Paint的線程會異步處理Paint()後面的代碼code
2.Paint()裏面是同步的,想要實現異步效果,再嵌套個加async的異步方法.blog
總之async 不加awit就是異步,加了就同步處理同步
實例測試:
private void button1_Click(object sender, EventArgs e) { textBox1.Text = "start\r\n"; aaa();//異步方法,若是裏面有awits的時候啓動異步,執行下一條代碼=====>>"textBox1.Text += "dfgfdgdfdfg\r\n";" textBox1.Text += "dfgfdgdfdfg\r\n"; } public async void aaa() { List<Task<PP>> plist = new List<Task<PP>>(); for (int i = 0; i < 10; i++) { Task<PP> p = Getp(i); // p.Start(); plist.Add(p); //PP p = await Getp(i); //textBox1.Text +=p.Name + "\r\n"; } textBox1.Text += "11111111111111111111\r\n"; while (plist.Count>0) { try { Task<PP> imageTask = await Task.WhenAny(plist); plist.Remove(imageTask); PP pppppp = await imageTask; textBox1.Text += pppppp.Name + "\r\n"; } catch (Exception exc) { MessageBox.Show(exc.Message); } } textBox1.Text += "22222222222222222222\r\n"; } public async Task<PP> Getp(int index) { PP p=new PP (); switch (index) { case 1: Thread.Sleep(1000); p.Index=index; p.Name=index.ToString(); return p; case 2: return await Task.Run(() => { Thread.Sleep(100); p.Index = index; p.Name = index.ToString(); return p; }); case 3: return await Task.Run(() => { Thread.Sleep(1000); p.Index = index; p.Name = index.ToString(); return p; }); case 4: return await Task.Run(() => { Thread.Sleep(500); p.Index = index; p.Name = index.ToString(); return p; }); default: return await Task.Run(() => { Thread.Sleep(2000); p.Index = index; p.Name = index.ToString(); return p; }); } }