使用時注意點
1 private async void button5_Click(object sender, EventArgs e) 2 { 3 /* 4 string i1 = await F1Async(); 5 MessageBox.Show("i1=" + i1); 6 string i2 = await F2Async(); 7 MessageBox.Show("i2=" + i2); 8 */ 9 Task<string> task1 = F1Async(); 10 Task<string> task2 = F2Async(); 11 string i1 = await task1; 12 MessageBox.Show("i1=" + i1); 13 string i2 = await task2; 14 MessageBox.Show("i2=" + i2); 15 } 16 17 static Task<string> F1Async() 18 { 19 MessageBox.Show("F1 Start"); 20 return Task.Run(() => { 21 System.Threading.Thread.Sleep(1000); 22 MessageBox.Show("F1 Run"); 23 return "F1"; 24 }); 25 } 26 27 static Task<string> F2Async() 28 { 29 MessageBox.Show("F2 Start"); 30 return Task.Run(() => { 31 System.Threading.Thread.Sleep(2000); 32 MessageBox.Show("F2 Run"); 33 return "F2"; 34 }); 35 }
如上兩個異步方法,在調用時,第一種調用提示框會按步驟彈出,而第二種則混亂的彈出,但這也不難理解因為多線程本來就是分片執行不按代碼順序;
第二種寫法的await是作為一個最后的保險作用,它的意義在於如果開始就執行了ok,如果沒執行則這步該執行了
不能使用async修飾而要調用異步方法怎么辦?
出現這種情況比較少,此時可以獲得Task<T>類型的返回值,獲取Task<T>.Result()方法,終止異步;
但請注意盡量少的使用Result()方法,他會造成數據上下文的死鎖問題。
如果返回值就是一個立即可以隨手可得的值,那么就用 Task.FromResult();
異步方法的風格轉換
Task.Factory.FromAsync()把 IAsyncResult 轉換為 Task,這樣 APM 風格的 api 也可以用 await 來調用
await修飾與並發執行的順序
被await修飾的異步方法,一定會按照順序執行並結束,所以如果沒有順序要求可以不使用await修飾並發任務
eg
1 private async void button1_Click(object sender, EventArgs e) 2 { 3 HttpClient hc = new HttpClient(); 4 var task1 = hc.GetStringAsync(textBox1.Text); 5 var task2 = hc.GetStringAsync(textBox2.Text); 6 var task3 = hc.GetStringAsync(textBox3.Text); 7 Task.WaitAll(task1, task2, task3); 8 label1.Text = task1.Result.Length.ToString(); 9 label2.Text = task2.Result.Length.ToString(); 10 label3.Text = task3.Result.Length.ToString(); 11 }
在接口中使用await
在接口定義是不能給接口做await修飾,然而為了增加可讀性,在方法明后添加async的特殊表示,在實現類中去添加await修飾即可
異常處理
TPL中,如果程序中出現異常,除非進行try...catch,否則有可能是感覺不到出了異常....
TPL中有時會拋出AggregateException可以同時catch住多個異常,這通常發生在並行多個任務的情況下
TPL與asp.net mvc
1. 返回值改為Task<ActionResult>即可,如果方法標記為async,連自己創建Task都省了
1 public async Task<ActionResult> Index() 2 { 3 return View(); 4 }
2. 為什么asp.net中用mvc能提升系統性能?
准確來講,不是提升性能,不會提高訪問速度,而是提升服務器的“吞吐量”,也就是可以處理的並發請求數
TPL常見的誤區
- 如果用了異步,那么就要async到底;async具有傳染性;
- 如果在使用異步api中摻雜了同步方法,則會打斷異步方法,有可能造成數據死鎖而且還會降低系統性能,so,不要輕易使用Wait、WaitAll
- 只要await、WhenAll不要task.Result、Wait、WaitAll
