C# Task異常捕獲


一般情況下,調用Task的Wait(),WaitAny(),WaitAll(),或者等待Result即可捕獲AggregateException異常

Task task = new Task(() =>
{
  throw new Exception("異步方法發生異常!")
});
task.Start();

try
{
    task.Wait();
}
catch(AggregateException ex)
{
    //打印異常具體信息
}

但是在異步方法中使用Wait強制阻塞當前線程,只是為了捕獲異常,這種迷之操作吾輩不屑之。思來想去,想到一個折中的方法,在Task的后續任務中捕獲異常,客官請看:

Task task = new Task(() =>
{
    throw new InvalidOperationException("並行任務中發生未知異常。");
});
task.Start();

Task endTsk = task.ContinueWith((task) =>
{
    throw task.Exception;
},TaskContinuationOptions.OnlyOnFaulted);

try
{
    endTsk.Wait();
}
catch(AggregateException ex)
{
    foreach(var er in ex.InnerExceptions)
    {
        Console.WriteLine($"異常類型{er.InnerException.GetType()}\n" +
                          $"異常來源:{er.InnerException.Source}\n" +
                          $"異常內容:{er.InnerException.Message}");
	}
}
Console.WriteLine("程序結束");
Console.ReadKey();

在后續任務中等待並捕獲異常是一個能夠接受的結果,而且等待的時間幾乎可以忽略不計。
當然,作為攻城獅,對於完美代碼的追求是不懈的,有沒有更合理的方式呢?
回答是Yes,就是使用事件通知來進行異常捕獲,如下所示:

public class AggregateExceptionArgs:EventArgs
{
    public AggregateException Exception {get;set;}
}



public static event EventHandler<AggregateExceptionArgs> AggregateExceptionCatched;

static void Main(string[] args)
{
    AggregateExceptionCatched += program_OnAggregateExcept;
    Task.Run(() =>
    {
        try
        {
            throw new ArgumentException("task參數異常!");
        }
        catch (Exception ex)
        {
            AggregateExceptionArgs exArgs = new AggregateExceptionArgs
            {
                Exception = new AggregateException(ex)
            };
            AggregateExceptionCatched(null, exArgs);
        }
    });
}

static void program_OnAggregateExcept(Object sender, AggregateExceptionArgs ex)
{
    foreach (var innEx in ex.Exception.InnerExceptions)
    {
        Console.WriteLine($"異常信息:{innEx.Message}");
    }
}

以上例子中,我定義了一個事件參數AggregateExceptionArgs,一個事件AggregateExceptionCatched,在主線程中,我為事件定義了事件處理方法program_OnAggregateExcept,當捕獲到異常時,將調用處理方法。
這種方式完全不會阻塞當前線程,如果是在winForm或者WPF窗體應用程序中,還能將異常交付UI線程處理。因為牆裂推薦這種方式捕獲異常。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM