Ho una domanda riguardante la gestione degli errori di .NET Task Parallel Library. In quali casi un AggregateException
può contenere più di 1 eccezione interna? So che questo può accadere per l'ex. quando si chiama Task.WaitAll(anArrayOfTasks)
e 2 o più attività generano un'eccezione, ma ci sono altri casi (ad esempio, può essere possibile che, se solo si attende l'esecuzione di 1 attività, si ottengano più di 1 eccezione interna)?Quando una eccezione Aggregate può contenere più di 1 eccezione interna?
risposta
Un'attività può generare un'eccezione aggregata che può intrinsecamente contenere più eccezioni interne. Ciò significa che dovresti sempre considerare un'eccezione aggregata con più eccezioni interne quando lavori con le attività. Anche se non stai utilizzando Task.WaitAll, l'attività che stai aspettando potrebbe attendere internamente per più attività secondarie. In alternativa, l'attività in attesa potrebbe restituire più eccezioni. Semplicemente non puoi sapere come chiamante.
Concordo sul fatto che, nel caso generale, dovresti assumere che potresti ottenere un elenco di eccezioni e progettare la gestione degli errori come tale, voglio solo sapere se la gestione di una singola attività asincrona che non dipende da altre attività asincrone creerà mai una situazione in cui viene superata più di 1 eccezione. – scripni
Potrebbe, solo potrebbe. Tuttavia non è molto probabile. SE l'attività interiore attende molteplici attività secondarie. Verrà creata una nuova AggregateException contenente 1 AggregateException contenente più eccezioni interne (possibilmente aggregate!). Pertanto è sempre consigliabile chiamare il metodo Flatten su AggregateException per ottenere tutte le eccezioni e gestirle come una raccolta – Polity
In che modo passeresti gli errori all'interfaccia utente in questo caso? Normalmente, se si esegue un'operazione, è possibile avere due risultati, o il successo o un errore. Progettare un'interfaccia utente per gestire in modo implicito gli elenchi di errori sembrerebbe confondere il mio parere, e avere due casi (uno per un errore e uno per più errori) sembra complicare eccessivamente le cose. Stavo pensando di gestire sempre al massimo 1 eccezione nell'interfaccia utente e di registrare tutte le eccezioni (e di presentare un messaggio all'utente per controllare il log degli errori ex). – scripni
Ciò può accadere se si dispone di un'attività "principale" e di una o più attività "secondarie" collegate al genitore. Ciò significa che l'attività principale termina solo quando tutte le sue attività secondarie terminano e le eccezioni delle attività figlio vengono anche propagate all'attività padre.
Prendiamo, per esempio, il seguente codice:
var task = Task.Factory.StartNew(
() =>
{
Task.Factory.StartNew(
() => { throw new Exception("inner"); },
TaskCreationOptions.AttachedToParent);
throw new Exception("outer");
});
Se Wait()
su quel compito, essa thows un AggregateException
, che assomiglia a questo:
AggregateException
Exception
: esternoAggregateException
Exception
: interno
Se non ti piace che possa contenere AggregateException
s all'interno AggregateException
s, è possibile utilizzare the Flatten()
method. C'è anche un altro metodo che può essere utilizzato per l'elaborazione di AggregateException
s: Handle()
.
Grazie per la risposta, +1 per aver menzionato il metodo Handle(), non lo sapevo. – scripni
Non correlato alla Libreria parallela. Supponiamo di avere un metodo per cancellare un elenco di file, ma alcuni sono bloccati. È possibile utilizzare un 'AggregateException' per rethrow per i file bloccati e continuare a eliminare il resto dei file. – nalply