第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案
一.?Task的各種返回值-Task<TResult>?
PS:?在前面章節(jié),我們介紹了Task類開啟線程、線程等待、線程延續(xù)的方式,但我們并沒有關(guān)注這些方式的返回值,其實(shí)他們都是有返回值的Task<TResult>,然后可以通過Task的實(shí)例調(diào)用Result屬性來獲取這個返回值。
下面我們分三類來介紹:
①:線程開啟類的返回值, 使用Task<TResult>接受,或者直接使用Task接受,通過 實(shí)例.Result 來獲取返回值。這里的線程開啟類有多種,eg: Task.Run()、 task.start()、 Task.Factory.StartNew() 等。
②:線程延續(xù)類的返回值. eg:ContinueWith。
③:線程條件延續(xù)類的返回值. eg:WhenAll和WhenAny。
?1. 線程開啟類的返回值
1 { 2 Task<string> task1 = Task.Factory.StartNew(() => 3 { 4 Console.WriteLine("我是子線程哦"); 5 return "ok"; 6 }); 7 task1.Wait(); 8 Console.WriteLine("我是主線程,我要讀取子線程task1的返回值為:{0}", task1.Result); 9 }2. ?線程延續(xù)類的返回值
1 {2 Task<int> task1 = Task.Run(() =>3 {4 Console.WriteLine("我是子線程1哦");5 return 2;6 });7 8 var task2 = task1.ContinueWith((t) =>9 { 10 Console.WriteLine("我是子線程2哦"); 11 12 //這里的t代表 task1 13 var num = t.Result + 2; 14 return num.ToString(); 15 }); 16 17 task2.Wait(); 18 Console.WriteLine("我是主線程,我要讀取子線程task1的返回值為:{0}", task1.Result); 19 Console.WriteLine("我是主線程,我要讀取子線程task2的返回值為:{0}", task2.Result); 20 }3. 線程條件延續(xù)類
1 {2 Task<int> task1 = Task.Run(() =>3 {4 Console.WriteLine("我是子線程1哦");5 return 1;6 });7 Task<int> task2 = Task.Run(() =>8 {9 Console.WriteLine("我是子線程2哦"); 10 return 2; 11 }); 12 13 var task = Task.WhenAny(new Task<int>[2] { task1, task2 }); 14 task.Wait(); 15 16 //下面的值可能是1,也可能是2 17 Console.WriteLine("我是主線程,我要讀取子線程task的返回值為:{0}", task.Result.Result); 18 }?
二. 通用線程異常處理方案
1. ?背景:我們想達(dá)到一個目的,當(dāng)同時開啟多個線程的時候,其中一個線程報錯,不影響其他線程的執(zhí)行,并且能把錯誤記下來。
2. ? 解決方案:多重try-catch,整個外側(cè)主線程一個try-catch,然后線程執(zhí)行業(yè)務(wù)再用一個try-catch包裹起來。
常規(guī)方式捕獲異常:
1 {2 try3 {4 for (int i = 0; i < 5; i++)5 {6 string name = string.Format("name{0}", i);7 var task = Task.Run(() =>8 {9 try 10 { 11 //模擬某個線程出錯 12 if (name == "name2") 13 { 14 throw new Exception(string.Format("線程執(zhí)行失敗,i={0}", name)); 15 } 16 else 17 { 18 Console.WriteLine(string.Format("線程執(zhí)行執(zhí)行成功,i={0}", name)); 19 } 20 } 21 catch (Exception ex) 22 { 23 Console.WriteLine(ex.Message); 24 } 25 26 }); 27 taskList.Add(task); 28 } 29 Task.WaitAll(taskList.ToArray()); 30 } 31 catch (Exception ex) 32 { 33 Console.WriteLine(ex.Message); 34 35 } 36 }運(yùn)行結(jié)果:我們發(fā)現(xiàn)所有的線程均執(zhí)行完畢,且name2執(zhí)行失敗,并捕獲。
?
補(bǔ)充一下:通過?AggregateException 類來捕獲異常。
?
1 {2 try3 {4 for (int i = 0; i < 5; i++)5 {6 string name = string.Format("name{0}", i);7 var task = Task.Run(() =>8 {9 throw new Exception(string.Format("線程執(zhí)行失敗,i={0}", name)); 10 }); 11 taskList.Add(task); 12 } 13 Task.WaitAll(taskList.ToArray()); 14 } 15 catch (AggregateException aes) 16 { 17 foreach (var item in aes.InnerExceptions) 18 { 19 Console.WriteLine(item.Message); 20 } 21 } 22 }總結(jié)
以上是生活随笔為你收集整理的第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信申请信用卡安全吗
- 下一篇: 现在申请房贷很难吗?为什么总是有些人被拒