2013-04-23 5 views
8

Mi chiedo, qualcuno ha di fronte casi, quando AggregateException.InnerExceptions.Count> 1?Qualcuno ha di fronte casi, quando AggregateException.InnerExceptions.Count> 1?

Es. Eccezione del wrapper TPL, che è stata sollevata nel corpo del task, in AggregateException. Ma non ho mai visto situazioni, quando c'era più di un'eccezione interiore.

Come è possibile ottenere questo risultato con TPL?
Come ottenere questo risultato con qualsiasi classe FCL (o un'altra libreria ampiamente utilizzata) (i campioni saranno utili)?

Lo so, c'è possibilità per creare tale istanza di AggregateException, ma la domanda riguarda una pratica. Te lo chiedo, perché voglio capire, qual è il modo migliore per gestire AggregateException.

+0

Un esempio: se si dispone di un'attività padre che crea uno o più task figlio (che sono impostati su "collegato al padre"), quindi compito figli e l'attività padre potrebbe generare un'eccezione e in questi casi terminerà con più che su eccezione nell'eccezione Aggregate restituita dall'attività padre. –

risposta

8

Il caso tipico è quando un'attività dipende da più attività e più di una di queste attività genera eccezioni. Ad esempio:

var t1 = Task.Factory.StartNew(() => { throw new Exception(); }); 
var t2 = Task.Factory.StartNew(() => Console.WriteLine("Innocuous")); 
var t3 = Task.Factory.StartNew(() => { throw new Exception(); }); 

// Output: 2 
var t4 = Task.WhenAll(t1, t2, t3) 
      .ContinueWith(t => Console.WriteLine(t.Exception.InnerExceptions.Count), 
          TaskContinuationOptions.OnlyOnFaulted); 
1

Come Ani ha detto questi AggregateExceptions possono essere creati tramite diversi successive Task s utilizzando continuazioni all'osservatore eccezioni.

Task t1 = Task.Factory.StartNew(() => { throw new Exception(); }); 
Task t2 = Task.Factory.StartNew(() => { throw new Exception(); }); 
Task t3 = Task.WhenAll(t1, t2) 
    .ContinueWith(t => t.Exception.InnerExceptions.Count(), 
    TaskContinuationOptions.OnlyOnFaulted); 

In genere si gestisce il AggregateException all'interno di una continuazione. Una continuazione può scoprire se un'eccezione è stata lanciata dall'antecedente Task dalla proprietà di eccezione dell'attività antecedente. Il seguente stampa i risultati di un NullReferenceException alla console

Task task1 = Task.Factory.StartNew (() => { throw null; }); 
Task task2 = task1.ContinueWith (ant => Console.Write(ant.Exception()); 

Se task1 genera un'eccezione e questa eccezione non viene catturata/interrogato dalla prosecuzione è considerato non gestita e l'applicazione muore. Con continuazioni è sufficiente per stabilire il risultato del compito tramite la parola chiave Status

asyncTask.ContinueWith(task => 
{ 
    // Check task status. 
    switch (task.Status) 
    { 
     // Handle any exceptions to prevent UnobservedTaskException.    
     case TaskStatus.RanToCompletion: 
      if (asyncTask.Result) 
      { 
       // Do stuff... 
      } 
      break; 
     case TaskStatus.Faulted: 
      if (task.Exception != null) 
       mainForm.progressRightLabelText = task.Exception.Flatten().Message; 
      else 
       mainForm.progressRightLabelText = "Operation failed!"; 
     default: 
      break; 
    } 
} 

Dove nel sopra Ho solo aspetto una sola eccezione - per assicurare che questo è il caso posso chiamare Flatten(). Se si prevedono altri tipi di eccezioni, è possibile scorrere i numeri InnerException come richiesto.

Spero che questo aiuti.

Problemi correlati