您好,登錄后才能下訂單哦!
本篇文章為大家展示了c# 基于任務的異步編程模式實現異常處理,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
1、沒有等待的調用異步方法
ThrowAfter方法是在一定延遲后拋出一個異常:
private async Task ThrowAfter(int ms,string message) { await Task.Delay(ms); Console.WriteLine("異步任務隨后將拋出異常。"); throw new Exception(message); }
DontHandle方法在調用異步方法時,由于有滯后性,所以使用try...catch...不能捕獲到異步方法中的異常。
public void DontHandle() { try { ThrowAfter(200, "異步方法拋出的異常"); } catch(Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("完成方法:DontHandle"); }
注意:返回void的異步方法不會等待。因為從async void方法拋出的異常無法捕獲。因此,異步方法最好返回一個Task類型。
2、異步方法的異常處理
異步方法異常的比較好的處理方式使使用await關鍵字,將其放在try/catch語句中。
public async void HandleOneError() { Console.WriteLine("HandleOneError方法開始執行。。。"); try { await ThrowAfter(2000, "異步方法拋出的異常"); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("完成方法:HandleOneError"); }
調用ThrowAfter方法后,HandleOneError會釋放線程,但它會在任務完成時保持對任務的引用。當異步方法拋出異常,會調用匹配的catch塊內的代碼。
3、多個異步方法的異常處理
如果調用多個異步方法,會有多個拋出異常,在捕獲異常時就會有問題。
public async void StartTwoTasks() { Console.WriteLine("StartTwoTasks方法開始執行。。。"); try { await ThrowAfter(2000, "first");//先執行該方法 await ThrowAfter(1000, "Second");//第一個異步方法正常執行完后才會執行該方法 } catch(Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("完成方法:StartTwoTasks"); }
StartTwoTasks方法中,調用了兩個異步方法。理論上認為,當第一個異步方法執行完,拋出異常后,緊接著就會調用第二個異步方法,并拋出異常。但實際上是第一個異步方法拋出異常之后,就會被catch捕獲,并不會執行第二個異步方法。因為這種類型中,在“基于任務的異步編程模式(TAP)”一文中解釋過,這種調用方法是等待第一個異步方法執行結束后,調用函數的線程控制權才會調用第二個異步方法,多個異步方法以此類推。但是當時我們使用了Task類中的WhenAll方法同時等待多個任務全部執行完,才執行后面的代碼。
public async void StartTwoTasksParallel() { Console.WriteLine("StartTwoTasksParallel方法開始執行。。。"); try { Task t1 = ThrowAfter(2000, "first");//先執行該方法 Task t2 = ThrowAfter(1000, "Second");//第一個異步方法執行完后才會執行該方法 await Task.WhenAll(t1, t2); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("完成方法:StartTwoTasksParallel"); }
StartTwoTasksParallel方法使用Task類的WhenAll方法,并行調用兩個不關聯的異步方法。該方法將等待所有任務結束后才結束調用,不論任何一個拋出異常都不會影響其他任務。但是,該方法只會捕獲第一個異常(先拋出異常的任務),其他異常將不會被顯示。
有一種方法可以獲取所有任務的異常信息,就是在try塊外聲明任務變量t1和t2,讓這兩個變量在catch塊內訪問。在catch塊中檢測任務的IsFaulted屬性確認任務的狀態,以判定是否出現異常,然后通過Task類的Exception.InnerException訪問異常信息本身。
4、使用AggregateException信息
Task.WhenAll方法返回一個Task的結果變量。catch語句只會捕捉到所有異步任務中的第一個異常,但是Task.WhenAll方法返回的Task類型結果變量中會包含所有任務都出現的異常。外部結果任務的Exception屬性是一個AggregateException類型,顯示所有異常只需要遍歷結果任務中的Exception的InnerExceptions屬性即可。
public async void ShowAggregatedException() { Console.WriteLine("ShowAggregatedException方法開始執行。。。"); Task taskResult = null; try { Task t1 = ThrowAfter(2000, "first");//先執行該方法 Task t2 = ThrowAfter(1000, "second");//第一個異步方法執行完后才會執行該方法 Task t3 = ThrowAfter(1500, "third");//第一個異步方法執行完后才會執行該方法 await (taskResult = Task.WhenAll(t1, t2, t3)); } catch (Exception ex) { Console.WriteLine("handle {0}",ex.Message); foreach (Exception ex1 in taskResult.Exception.InnerExceptions) { Console.WriteLine("Inner exception {0}", ex1.Message); } } Console.WriteLine("完成方法:ShowAggregatedException"); }
上述內容就是c# 基于任務的異步編程模式實現異常處理,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。