Mam pytanie dotyczące obsługi błędów biblioteki .NET zadania. W których przypadkach numer AggregateException
może zawierać więcej niż jeden wyjątek wewnętrzny? Wiem, że to może się zdarzyć na przykład. podczas wywoływania Task.WaitAll(anArrayOfTasks)
, a 2 lub więcej zadań rzuca wyjątek, ale czy są jakieś inne przypadki (tj. czy jest możliwe, że jeśli oczekujesz tylko na 1 zadanie, otrzymasz więcej niż 1 wyjątek wewnętrzny)?Kiedy wyjątek AggregateException może zawierać więcej niż jeden wyjątek wewnętrzny?
Odpowiedz
Zadanie może zgłosić zagregowany wyjątek, który z natury może zawierać wiele wewnętrznych wyjątków. Oznacza to, że zawsze należy rozważyć zagregowany wyjątek z wieloma wewnętrznymi wyjątkami podczas pracy z zadaniami. Nawet jeśli nie używasz Task.WaitAll, zadanie, na które czekasz, może wewnętrznie czekać na wiele podzadań. Ewentualnie zadanie oczekujące może zwrócić wiele wyjątków. Po prostu nie możesz wiedzieć jako dzwoniący.
Zgadzam się, że w ogólnym przypadku należy założyć, że można uzyskać listę wyjątków i zaprojektować obsługę błędów jako taką, po prostu chcę wiedzieć, czy obsługa jednego asynchronicznego zadania, które nie zależy od innych zadań asynchronicznych, kiedykolwiek stworzy sytuacja, w której przechodzą więcej niż jeden wyjątek. – scripni
Może, po prostu. Jednak nie jest to bardzo prawdopodobne. JEŚLI wewnętrzne zadanie czeka na wiele zadań podrzędnych. Zostanie utworzony nowy wyjątek AggregateException zawierający 1 wyjątek AggregateException zawierający wiele wyjątków wewnętrznych (prawdopodobnie agregujących!). Dlatego zawsze dobrym zwyczajem jest wywoływanie metody Flatten przez wyjątek AggregateException, aby uzyskać wszystkie wyjątki i traktować je jako kolekcję. – Polity
W jaki sposób przekażesz błędy do interfejsu użytkownika w tym przypadku? Zwykle, jeśli wykonujesz operację, możesz mieć dwa wyniki, albo sukces, albo błąd. Projektowanie interfejsu do pośredniego obsługiwania list błędów wydaje się być mylące w mojej opozycji, a posiadanie dwóch przypadków (jeden za jeden błąd i jeden za wiele błędów) wydaje się nadkomplikować rzeczy. Myślałem o tym, że zawsze będę obsługiwał najwyżej jeden wyjątek w interfejsie użytkownika i rejestrować wszystkie wyjątki (i wyświetlać komunikat użytkownikowi, aby sprawdzić dziennik błędów dla przykładu). – scripni
Może się tak zdarzyć, jeśli masz zadanie "rodzica" i jedno lub więcej zadań "podrzędnych", które są dołączone do rodzica. Oznacza to, że zadanie nadrzędne zakończy się dopiero po zakończeniu wszystkich zadań podrzędnych, a wyjątki od zadań podrzędnych będą również propagowane do zadania nadrzędnego.
Weźmy, na przykład, następujący kod:
var task = Task.Factory.StartNew(
() =>
{
Task.Factory.StartNew(
() => { throw new Exception("inner"); },
TaskCreationOptions.AttachedToParent);
throw new Exception("outer");
});
Jeśli Wait()
tego zadania, to thows się AggregateException
, który wygląda tak:
AggregateException
Exception
: zewnętrznyAggregateException
Exception
: wewnętrzna
Jeśli ci się nie podoba, że może ona zawierać AggregateException
s wewnątrz AggregateException
s, można użyć the Flatten()
method. Istnieje również inna metoda, która może być używana do przetwarzania AggregateException
s: Handle()
.
Dzięki za odpowiedź, +1 za wymienienie metodą Handle(), nie wiedziałem o tym. – scripni
Nie powiązane z Biblioteką równoległą. Załóżmy, że masz metodę usuwania listy plików, ale niektóre są zablokowane. Możesz użyć 'AggregateException' do ponownego wyrzucenia zablokowanych plików i kontynuować usuwanie pozostałych plików. – nalply