C# 異步編程Task整理(二)異常捕捉

1、在任務並行庫中,若是對任務運行Wait、WaitAny、WaitAll等方法,或者求Result屬性,都能捕獲到AggregateException異常。html

能夠將AggregateException異常看作是任務並行庫編程中最上層的異常。編程

在任務中捕獲的異常,最終都應該包裝到AggregateException中。一個任務並行庫異常的簡單處理示例以下:異步

static void TestTwo()
{
    Task t1= Task.Factory.StartNew(() => {

        throw new Exception("執行失敗");
    });
    try
    {
        //主線程等待,能夠 捕捉異常
        t1.Wait();
    }
    catch (AggregateException ex)
    {
        foreach (var item in ex.InnerExceptions)
        {
            Console.WriteLine("異常類型:{0}{1}來自:  {2} {3} 異常內容:{4} ", item.GetType(),  
        Environment.NewLine, item.Source,  
        Environment.NewLine, item.Message);
        }
        Console.Write(ex.Message);
    }
}

2、方式2使用主線程委託,這種方式比較推薦異步編程

 在這個例子中,咱們聲明瞭一個委託AggregateExceptionCatchHandler,它接受兩個參數,一個是事件的通知者;另外一個是事件變量AggregateExceptionArgs。AggregateExceptionArgs是爲了包裝異常而新建的一個類型。在主線程中,咱們爲事件AggregateExceptionCatched分配了事件處理方法Program_AggregateExceptionCatched,當任務Task捕獲到異常時,代碼引起事件。

這種方式徹底沒有阻滯主線程。若是是在Winform或WPF窗體程序中,要在事件處理方法中處理UI界面,還能夠將異常信息交給窗體的線程模型去處理。因此,最終建議你們採用事件通知的模型處理Task中的異常。post

//定義AggregateException 的事件委託
static event EventHandler<AggregateExceptionArgs> AggregateExceptionCatched;
static void TestThree()
{
    AggregateExceptionCatched += new EventHandler<AggregateExceptionArgs>(Program_AggregateExceptionCatched);

    Task t1 = new Task(() =>
    {
        try
        {
            throw new InvalidOperationException("任務並行編碼 中產生未知錯誤");
        }
        catch (Exception ex)
        {
            AggregateExceptionArgs args = new AggregateExceptionArgs()
            {
                AggregateException = new AggregateException(ex)
            };
            //使用主線程委託代理,處理子線程 異常
            //這種方式沒有阻塞 主線程或其餘線程
            AggregateExceptionCatched?.Invoke(null, args);
        }
    });
    t1.Start();
}
static void Program_AggregateExceptionCatched(object sender, AggregateExceptionArgs e)
{
    foreach (var item in e.AggregateException.InnerExceptions)
    {
        Console.WriteLine("異常類型:{0}{1}來自:{2}{3}異常內容:{4}",
            item.GetType(), Environment.NewLine, item.Source,
            Environment.NewLine, item.Message);
    }
}
//定義異常參數處理
public class AggregateExceptionArgs : EventArgs
{
    public AggregateException AggregateException { get; set; }
}

3、TaskScheduler.UnobservedTaskException編碼

注意 任務調度器TaskScheduler提供了這樣一個功能,它有一個靜態事件用於處理未捕獲到的異常。通常不建議這樣使用,由於事件回調是在進行垃圾回收的時候才發生的。url

static void TestFourth()
{
    TaskScheduler.UnobservedTaskException += new EventHandler<UnobservedTaskExceptionEventArgs>(TaskScheduler_UnobservedTaskException);

    Task t1 = new Task(() =>
    {
        throw new Exception("任務並行編碼中 產生 未知錯誤");
    });
    t1.Start();
    Console.ReadKey();//主線程等待
    t1 = null;
    //GC.Collect(0); //只有在回收t1對象 的時候纔會觸發UnobservedTaskException
    Console.WriteLine("主線程立刻結束");
    Console.Read();
}
static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
    foreach (Exception item in e.Exception.InnerExceptions)
    {
        Console.WriteLine("異常類型:{0}{1}來自:{2}{3}異常內容:{4}",
            item.GetType(), Environment.NewLine, item.Source,
            Environment.NewLine, item.Message);
    }
    //將異常標識爲已經觀察到  
    e.SetObserved();
}

更多 :spa

C# 異步編程Task整理(一)線程

C# Process獲取當前進程信息代理

C# ApartmentState 枚舉,指定線程單元狀態

相關文章
相關標籤/搜索