簡體   English   中英

處理來自異步並行任務的多個異常

[英]Handling multiple exceptions from async parallel tasks

問題

有幾個任務是並行運行的,all,none或者其中任何一個都可能拋出異常。 當所有任務完成后,必須報告所有可能發生的異常(通過日志,電子郵件,控制台輸出......等等)。

預期的行為

我可以使用Task.WhenAll(tasks) lambdas通過linq構建所有任務,然后等待它們與Task.WhenAll(tasks)並行運行。 然后我可以捕獲AggregateException並報告每個單獨的內部異常。

實際行為

拋出了AggregateException ,但它只包含一個內部異常,無論拋出多少個別異常。

最小的完整可驗證的例子

static void Main(string[] args)
{
    try
    {
        ThrowSeveralExceptionsAsync(5).Wait();
    }
    catch (AggregateException ex)
    {
        ex.Handle(innerEx =>
        {
            Console.WriteLine($"\"{innerEx.Message}\" was thrown");
            return true;
        });
    }

    Console.ReadLine();
}

private static async Task ThrowSeveralExceptionsAsync(int nExceptions)
{
    var tasks = Enumerable.Range(0, nExceptions)
        .Select(async n =>
        {
            await ThrowAsync(new Exception($"Exception #{n}"));
        });

    await Task.WhenAll(tasks);
}

private static async Task ThrowAsync(Exception ex)
{
    await Task.Run(() => {
        Console.WriteLine($"I am going to throw \"{ex.Message}\"");
        throw ex;
    });
}

產量

請注意,由於競爭條件,“我要投擲”消息的輸出順序可能會發生變化。

I am going to throw "Exception #0"
I am going to throw "Exception #1"
I am going to throw "Exception #2"
I am going to throw "Exception #3"
I am going to throw "Exception #4"
"Exception #0" was thrown

這是因為await “解包”聚合異常並且總是拋出第一個異常(如await文檔中所述),即使等待Task.WhenAll顯然會導致多個錯誤。 您可以訪問聚合異常,例如:

var whenAll = Task.WhenAll(tasks);
try {
    await whenAll;
}
catch  {
    // this is `AggregateException`
    throw whenAll.Exception;
}

或者你可以循環遍歷任務並檢查每個任務的狀態和異常。

請注意,在修復之后,您還需要做一件事:

try {
    ThrowSeveralExceptionsAsync(5).Wait();
}
catch (AggregateException ex) {
    // flatten, unwrapping all inner aggregate exceptions
    ex.Flatten().Handle(innerEx => {
        Console.WriteLine($"\"{innerEx.Message}\" was thrown");
        return true;
    });
}

因為ThrowSeveralExceptionsAsync返回的任務包含我們拋出的AggregateException ,包含在另一個AggregateException

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM