2012-03-28 3 views
8

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?

+0

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

Odpowiedz

4

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.

+0

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

+0

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

+0

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

5

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ętrzny
    • AggregateException
      • 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().

+0

Dzięki za odpowiedź, +1 za wymienienie metodą Handle(), nie wiedziałem o tym. – scripni