多線程(7)多線程中的異常處理
阿新 • • 發佈:2017-07-01
sch img 技術 pro art div alt 使用 archive
多線程使用過程中,除了線程同步的問題要考慮外,異常處理也是經常要面對的事情。
默認主線程捕獲不到異步線程的異常
如下代碼:
1 namespace ConsoleApplication29 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //異步線程的異常處理 8 try 9 { 10 Task.Factory.StartNew(() => 11View Code{ 12 throw new Exception("異步線和發生異常了!"); 13 }); 14 } 15 catch (Exception ex) 16 { 17 //這裏是捕獲不到的 18 Console.WriteLine(ex.ToString()); 19 } 20 21 Console.ReadKey();22 } 23 } 24 }
常用的異常處理方法
1,在異步線程內部使用try/catch
如下代碼:
1 namespace ConsoleApplication29 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //異步線程的異常處理 8 //1,在異步線程內部使用try/catch 9 Task.Factory.StartNew(() => 10View Code{ 11 try 12 { 13 throw new Exception("異步線和發生異常了!"); 14 } 15 catch (Exception ex) 16 { 17 Console.WriteLine(ex.ToString()); 18 } 19 }); 20 21 Console.ReadKey(); 22 } 23 } 24 }
運行結果:
2,調用Task的Wait方法
如下代碼:
註意:
除了調用Task的Wait方法後,在主線程可以捕獲異常外,對於有返回值的Task,只要接收了它的返回值就不再需要調用Wait方法了。
1 namespace ConsoleApplication29 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //異步線程的異常處理 8 //2,調用Task的Wait方法 9 try 10 { 11 var task = Task.Factory.StartNew(() => 12 { 13 throw new Exception("異步線和發生異常了!"); 14 }); 15 task.Wait(); 16 } 17 catch (Exception ex) 18 { 19 Console.WriteLine(ex.ToString()); 20 } 21 22 Console.ReadKey(); 23 } 24 } 25 }View Code
運行結果:
3,在Task的ContinueWith方法中讀取Task的Exception屬性
如下代碼:
1 namespace ConsoleApplication29 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //異步線程的異常處理 8 //3,在Task的ContinueWith方法中讀取Task的Exception屬性 9 Task.Factory.StartNew(() => 10 { 11 throw new Exception("異步線和發生異常了!"); 12 }).ContinueWith(t => 13 { 14 if (t.IsFaulted) 15 { 16 Console.WriteLine(t.Exception.InnerException); 17 } 18 }, TaskContinuationOptions.OnlyOnFaulted); 19 20 Console.ReadKey(); 21 } 22 } 23 }View Code
運行結果:
4,全局設置TaskScheduler.UnobservedTaskException
如果異步線程裏的異常沒有被處理,也沒有調用Task.Wait方法將異常傳給主線程處理,最嚴重的後果可能會導致整個應用程序奔潰。詳細原因參考:System.Threading.Tasks.Task引起的IIS應用程序池崩潰
所以,為了保證應用程序不會因為異步線程的異常未被處理導致掛掉,推薦的做法是,全局設置TaskScheduler.UnobservedTaskException。
如果是web程序,可以在Global的Application_Start事件中進行設置,如下代碼:
1 protected override void Application_Start(object sender, EventArgs e) 2 { 3 System.Threading.Tasks.TaskScheduler.UnobservedTaskException += (s, v) => 4 { 5 v.SetObserved(); 6 }; 7 }View Code
多線程(7)多線程中的異常處理