Gestire le eccezioni in Task paralleli

Tempo fa ho scritto un post su come eseguire Task in parallelo o in seriale. Questa volta invece parleremo di come gestire correttamente le eccezioni in Task paralleli.

Supponiamo di dover effettuare delle chiamate ad alcuni microservizi. Magari la nostra applicazione è un API Gateway e dobbiamo aggregare i dati.

Supponiamo che le chiamate siano indipendenti fra di loro e possano quindi essere eseguite in parallelo. Come lo sviluppiamo? Molto semplicemente possiamo usare Task.WaitAll() oppure, ancora meglio, Task.WhenAll(). Qualcosa del genere:

Task.WhenAll() restituisce un Task quindi possiamo usare il costrutto async/await evitando cosi’ di bloccare il thread corrente.

Perfetto, ora supponiamo peró che qualcuna delle chiamate fallisca e lanci un’eccezione. Come possiamo gestire gli errori evitando di perdere informazioni preziose? Un blocco try/catch è sicuramente un buon inizio:

Questo funziona bene finché abbiamo una sola eccezione. Se piú chiamate falliscono Task.WhenAll() ci rilancerá purtoppo soltanto la prima. Questa e’ una delle differenze principali rispetto a Task.WaitAll() : quest’ultimo infatti raggruppa tutte le eccezioni e le rilancia all’interno di una AggregateException .

Quindi cosa possiamo fare? Passare a Task.WaitAll()? No, c’e’ una soluzione migliore.

Il trucco praticamente sta nel non usare await direttamente su Task.WhenAll(), bensí salvarne il risultato in una variabile. All’interno del blocco try/catch possiamo poi accedere alla property task.Exception, che sará di tipo AggregateException. A questo punto poi possiamo fare quello che vogliamo accedendo alla collezione InnerExceptions:

Come al solito ho pubblicato su Github un piccolo repository. All’interno troverete una console application in dotNet Core con vari esempi su come gestire le eccezioni dei in parallelo.

Gestire le eccezioni in Task paralleli
Torna su