Task異常捕獲的方式


    這節來講一下如何捕獲Task的異常。

    當Task運行中出現了異常,正常情況下我們在主線程的Try是捕獲不到的,而如果在Task內部寫try,出現了異常我們會完全不知道。下面就來介紹幾個主線程捕獲Task異常的方法。

 

阻塞線程式

    我們可以使用Wait(),WaitAny(),WaitAll()來捕獲Task的異常,詳見下圖:

    捕獲Task異常,准確來說要用AggregateException類,右邊是運行結果,成功捕獲到了異常信息,其它兩個等待也是類似的用法,不熟悉的小伙伴可以參見前文:等待多個異步任務的方法

    在等待多個Task異常時,可以訪問異常對象的InnerExceptions屬性來遍歷所有的異常:

     上述異常捕獲的解決方案,因為涉及到了等待,所以會阻塞主線程,並且如果異常發生在等待之前,同樣是不能捕獲到,所以這種方式,雖然簡單,但是使用場景並不多。

 

異步式

    我們知道Task有個ContinueWith方法,它會在Task完成后繼續異步執行傳入的委托,我們可以通過這個方法實現異常捕獲,請看如下代碼:

    因為是異步執行,所以這樣不會阻塞主線程。

事件式

    事件式的思路是在主線程中定義事件,在Task中通過觸發事件的形式讓主線程捕獲到異常,請看代碼:

    首先定義一個事件參數:

internal class TaskExceptionEventArgs:EventArgs
{
    /// <summary>
    /// 存放Task引發的異常對象
    /// </summary>
    public AggregateException AggregateException { get; set; }  
}

    主代碼如下:

class Program
{
    private static event EventHandler<TaskExceptionEventArgs> taskExceptionEventHandler;
    static void Main(string[] args)
    {
        //為事件添加事件處理器
        taskExceptionEventHandler = (sender, aeArgs) =>
        {
            Console.WriteLine(aeArgs.AggregateException.Message);
        };
        Task.Run(async () =>
        {
            await Task.Delay(2 * 1000);
            try
            {
                throw new AggregateException("內部異常1");
            }
            catch (AggregateException ex)
            {
                //觸發事件,並傳入參數
                taskExceptionEventHandler.Invoke(null, new TaskExceptionEventArgs
                {
                    AggregateException = ex
                });
            }
        });
    }
}

 

這樣用法很靈活,而且拿到的是最直接的異常對象,並且不用等待Task執行完畢。

 


免責聲明!

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



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