[英]Proper way to handle C# AggregateException
我有一個關於何時使用WhenAll()處理聚合異常的安全性的問題。 看起來自然的位置會在catch塊內,因為如果catch塊永遠不會觸發,那就意味着沒有異常可以處理。 但我看到很多代碼都有一個空的catch塊,並在處理任何找到的異常(包括在MS網站上)之前檢查是否存在AggregateException。
public async Task MyMethod() {
var tasks = new List<Task>();
for (var i = 0; i < 10; i++) {
tasks.Add(DoSthAsync());
}
var masterTask = Task.WhenAll(tasks);
try {
var results = await masterTask;
} catch {
// Safe to access masterTask here and handle aggregate exceptions? Have all tasks completed?
foreach (var ex in masterTask.Exception.innerExceptions) {
HandleException(ex);
}
}
// Or necessary to check for and handle aggregate exceptions here?
if (masterTask.Exception != null) {
foreach (var ex in masterTask.Exception.innerExceptions) {
HandleException(ex);
}
}
}
public async Task DoSthAsync() {
// ...
}
似乎自然的地方將在捕獲區內
是的,那會很好。 Task.WhenAll
返回在所有任務完成后完成的任務。 因此,在您的情況下,當您的代碼進入catch
塊時, masterTask
已完成,這意味着所有tasks
都已完成。
您發布的代碼有效,因為Task.WhenAll
返回的任務僅在所有子任務完成后才完成。
為什么代碼這樣做? 為什么沒有catch (Exception ex)
? 這是因為等待只拋出第一個內部異常。 如果您需要訪問多個異常,則此代碼模式是一種很好的方法。 您也可以執行catch (AggregateException ex)
並使用該對象。 這是同一個對象。
我個人避免使用這樣的catch
。 基本上它使用控制流的異常。 這使得調試更加困難並且可能導致冗長的代碼。
我喜歡這個:
var whenAllTask = Task.WhenAll(...);
await whenAllTask.ContinueWith(_ => { }); //never throws
if (whenAllTask.Exception != null) ... //handle exceptions
我將.ContinueWith(_ => { })
位轉換為WhenCompleted
擴展方法,以使代碼看起來干凈。
然后你想知道檢查異常的第二種方法是否是一個好主意:
// Or necessary to check for and handle aggregate exceptions here?
if (masterTask.Exception != null) {
foreach (var ex in masterTask.Exception.innerExceptions) {
HandleException(ex);
}
}
你當然可以這樣做。 基本上它是一樣的。 使用在特定情況下更方便的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.