欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c# 基于任務(wù)的異步編程模式(TAP)的異常處理

 更新時(shí)間:2020年11月02日 09:08:42   作者:一只獨(dú)行的猿  
這篇文章主要介紹了c# 基于任務(wù)的異步編程模式的異常處理方法,幫助大家更好的理解和學(xué)習(xí)c#

在前面講到了《基于任務(wù)的異步編程模式(TAP)》,但是如果調(diào)用異步方法,沒(méi)有等待,那么調(diào)用異步方法的線程中使用傳統(tǒng)的try/catch塊是不能捕獲到異步方法中的異常。因?yàn)樵诋惒椒椒▓?zhí)行出現(xiàn)異常之前,已經(jīng)執(zhí)行完畢。

1、沒(méi)有等待的調(diào)用異步方法

ThrowAfter方法是在一定延遲后拋出一個(gè)異常:

private async Task ThrowAfter(int ms,string message)
{
  await Task.Delay(ms);
  Console.WriteLine("異步任務(wù)隨后將拋出異常。");
  throw new Exception(message);
}

DontHandle方法在調(diào)用異步方法時(shí),由于有滯后性,所以使用try...catch...不能捕獲到異步方法中的異常。

public void DontHandle()
{
  try
  {
    ThrowAfter(200, "異步方法拋出的異常");
  }
  catch(Exception ex)
  {
    Console.WriteLine(ex.Message);
  }
  Console.WriteLine("完成方法:DontHandle");
}

注意:返回void的異步方法不會(huì)等待。因?yàn)閺腶sync void方法拋出的異常無(wú)法捕獲。因此,異步方法最好返回一個(gè)Task類(lèi)型。

2、異步方法的異常處理

異步方法異常的比較好的處理方式使使用await關(guān)鍵字,將其放在try/catch語(yǔ)句中。

public async void HandleOneError()
{
  Console.WriteLine("HandleOneError方法開(kāi)始執(zhí)行。。。");
  try
  {
    await ThrowAfter(2000, "異步方法拋出的異常");
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);
  }
  Console.WriteLine("完成方法:HandleOneError");
}

調(diào)用ThrowAfter方法后,HandleOneError會(huì)釋放線程,但它會(huì)在任務(wù)完成時(shí)保持對(duì)任務(wù)的引用。當(dāng)異步方法拋出異常,會(huì)調(diào)用匹配的catch塊內(nèi)的代碼。

3、多個(gè)異步方法的異常處理

如果調(diào)用多個(gè)異步方法,會(huì)有多個(gè)拋出異常,在捕獲異常時(shí)就會(huì)有問(wèn)題。

public async void StartTwoTasks()
{
  Console.WriteLine("StartTwoTasks方法開(kāi)始執(zhí)行。。。");
  try
  {
    await ThrowAfter(2000, "first");//先執(zhí)行該方法
    await ThrowAfter(1000, "Second");//第一個(gè)異步方法正常執(zhí)行完后才會(huì)執(zhí)行該方法
  }
  catch(Exception ex)
  {
    Console.WriteLine(ex.Message);
  }
  Console.WriteLine("完成方法:StartTwoTasks");
}

StartTwoTasks方法中,調(diào)用了兩個(gè)異步方法。理論上認(rèn)為,當(dāng)?shù)谝粋€(gè)異步方法執(zhí)行完,拋出異常后,緊接著就會(huì)調(diào)用第二個(gè)異步方法,并拋出異常。但實(shí)際上是第一個(gè)異步方法拋出異常之后,就會(huì)被catch捕獲,并不會(huì)執(zhí)行第二個(gè)異步方法。因?yàn)檫@種類(lèi)型中,在“基于任務(wù)的異步編程模式(TAP)”一文中解釋過(guò),這種調(diào)用方法是等待第一個(gè)異步方法執(zhí)行結(jié)束后,調(diào)用函數(shù)的線程控制權(quán)才會(huì)調(diào)用第二個(gè)異步方法,多個(gè)異步方法以此類(lèi)推。但是當(dāng)時(shí)我們使用了Task類(lèi)中的WhenAll方法同時(shí)等待多個(gè)任務(wù)全部執(zhí)行完,才執(zhí)行后面的代碼。

public async void StartTwoTasksParallel()
{
  Console.WriteLine("StartTwoTasksParallel方法開(kāi)始執(zhí)行。。。");
  try
  {
    Task t1 = ThrowAfter(2000, "first");//先執(zhí)行該方法
    Task t2 = ThrowAfter(1000, "Second");//第一個(gè)異步方法執(zhí)行完后才會(huì)執(zhí)行該方法
    await Task.WhenAll(t1, t2);
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);
  }
  Console.WriteLine("完成方法:StartTwoTasksParallel");
}

StartTwoTasksParallel方法使用Task類(lèi)的WhenAll方法,并行調(diào)用兩個(gè)不關(guān)聯(lián)的異步方法。該方法將等待所有任務(wù)結(jié)束后才結(jié)束調(diào)用,不論任何一個(gè)拋出異常都不會(huì)影響其他任務(wù)。但是,該方法只會(huì)捕獲第一個(gè)異常(先拋出異常的任務(wù)),其他異常將不會(huì)被顯示。

有一種方法可以獲取所有任務(wù)的異常信息,就是在try塊外聲明任務(wù)變量t1和t2,讓這兩個(gè)變量在catch塊內(nèi)訪問(wèn)。在catch塊中檢測(cè)任務(wù)的IsFaulted屬性確認(rèn)任務(wù)的狀態(tài),以判定是否出現(xiàn)異常,然后通過(guò)Task類(lèi)的Exception.InnerException訪問(wèn)異常信息本身。

4、使用AggregateException信息

Task.WhenAll方法返回一個(gè)Task的結(jié)果變量。catch語(yǔ)句只會(huì)捕捉到所有異步任務(wù)中的第一個(gè)異常,但是Task.WhenAll方法返回的Task類(lèi)型結(jié)果變量中會(huì)包含所有任務(wù)都出現(xiàn)的異常。外部結(jié)果任務(wù)的Exception屬性是一個(gè)AggregateException類(lèi)型,顯示所有異常只需要遍歷結(jié)果任務(wù)中的Exception的InnerExceptions屬性即可。

public async void ShowAggregatedException()
{
  Console.WriteLine("ShowAggregatedException方法開(kāi)始執(zhí)行。。。");
  Task taskResult = null;
  try
  {
    Task t1 = ThrowAfter(2000, "first");//先執(zhí)行該方法
    Task t2 = ThrowAfter(1000, "second");//第一個(gè)異步方法執(zhí)行完后才會(huì)執(zhí)行該方法
    Task t3 = ThrowAfter(1500, "third");//第一個(gè)異步方法執(zhí)行完后才會(huì)執(zhí)行該方法
    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# 基于任務(wù)的異步編程模式(TAP)的異常處理的詳細(xì)內(nèi)容,更多關(guān)于c# 異步編程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用C#代碼獲取存儲(chǔ)過(guò)程返回值

    使用C#代碼獲取存儲(chǔ)過(guò)程返回值

    這篇文章主要介紹了使用C#代碼獲取存儲(chǔ)過(guò)程返回值,需要的朋友可以參考下
    2015-11-11
  • C#開(kāi)發(fā)教程之ftp操作方法整理

    C#開(kāi)發(fā)教程之ftp操作方法整理

    這篇文章主要介紹了C#開(kāi)發(fā)教程之ftp操作方法整理的相關(guān)資料,需要的朋友可以參考下
    2016-07-07
  • C#實(shí)現(xiàn)圖片切割的方法

    C#實(shí)現(xiàn)圖片切割的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)圖片切割的方法,涉及C#使用Graphics實(shí)現(xiàn)圖片屬性的相關(guān)設(shè)置、保存等操作技巧,需要的朋友可以參考下
    2017-06-06
  • C#操作Access通用類(lèi)實(shí)例

    C#操作Access通用類(lèi)實(shí)例

    這篇文章主要介紹了C#操作Access通用類(lèi),實(shí)例分析了C#操作access的各種常見(jiàn)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-06-06
  • WPF TextBox和PasswordBox添加水印

    WPF TextBox和PasswordBox添加水印

    這篇文章主要為大家詳細(xì)介紹了WPF TextBox和PasswordBox添加水印的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • C#圓角窗體簡(jiǎn)單實(shí)現(xiàn)方法

    C#圓角窗體簡(jiǎn)單實(shí)現(xiàn)方法

    這篇文章主要介紹了C#圓角窗體簡(jiǎn)單實(shí)現(xiàn)方法,涉及C#窗體設(shè)置的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • C#?WPF調(diào)用QT窗口的方法

    C#?WPF調(diào)用QT窗口的方法

    本文主要介紹了C#?WPF調(diào)用QT窗口的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • C# 開(kāi)發(fā)日志本地化工具

    C# 開(kāi)發(fā)日志本地化工具

    這篇文章主要介紹了C# 開(kāi)發(fā)日志本地化工具的步驟,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-02-02
  • c# 實(shí)現(xiàn)漢諾塔游戲

    c# 實(shí)現(xiàn)漢諾塔游戲

    這篇文章主要介紹了c# 實(shí)現(xiàn)漢諾塔游戲的示例,幫助大家更好的理解和使用c# 編程語(yǔ)言,感興趣的朋友可以了解下
    2020-11-11
  • c#泛型學(xué)習(xí)詳解 創(chuàng)建線性鏈表

    c#泛型學(xué)習(xí)詳解 創(chuàng)建線性鏈表

    Visual C# 2.0 的一個(gè)最受期待的(或許也是最讓人畏懼)的一個(gè)特性就是對(duì)于泛型的支持。這篇文章將告訴你泛型用來(lái)解決什么樣的問(wèn)題,以及如何使用它們來(lái)提高你的代碼質(zhì)量,還有你不必恐懼泛型的原因
    2014-01-01

最新評(píng)論