Programmazione asincrona deadlock

Programmazione Asincrona e void

Uno degli errori da evitare nella programmazione asincrona in c# (tramite async e await) è quello di creare metodi che restituiscono void.

L’utilizzo di metodi asincroni che ritornano uno void (async void) introducono due tipologie di problemi:

  • non è possibile determinare quando il task è stato completato
  • le eccezioni che vengono generate al suo interno producono come risultato la terminazione del processo

Analisi del completamento di un metodo che ritorna async void

Analizziamo il codice seguente:

Se creiamo un’istanza della classe FooBar e proviamo ad eseguire il metodo Biz, poichè non ritorna un Task, non possiamo in nessun modo verificare quando è terminato. E’ sufficiente modificare la firma del metodo nel seguente modo

per poter poter gestire la Wait nel seguente modo:

L’unico caso in cui utilizzare async void è quello in cui dobbiamo realizzare un gestore di eventi

Ad esempio, se volessimo gestire l’evento click di un pulsante potremmo scrivere qualcosa di simile:

In questo caso è consentito l’utilizzo di async void perchè la scrittura di un gestore di eventi che restituisce dati è spesso molto complicata, e non sempre è la soluzione ottimale. Un gestore di eventi “normalmente” restituisce un void quindi possiamo pensare di realizzare un metodo di tipo async void.

Gestione delle eccezioni nel caso di metodi che ritornano async void

Il secondo problema riguarda la gestione degli errori (e quindi come vengono gestite le eccezioni) all’interno di metodi che restituisco async void.

Le eccezioni che vengono generate da un metodo che ritorna un async void sono gestite in maniera differente rispetto a quelle che ritornano un Task

Quando si verifica un’eccezione in un metodo che ritorna un Task o un Task<T>, viene catturata e posizionato all’interno dell’oggetto Task. Quando viene generata un’eccezione all’interno di un metodo async void potrebbe essere gestitata utilizzanod la classe SyncronizationContex al momento della chiamata asincrona. Questo tipo di eccezione non può essere “osservata” in maniera tradizionale, ma solo attraverso AppDomain.UnhandledException: sicuramente non di semplice analisi.

Analizziamo il seguente codice:

anche se la chiamata della funzione  ThrowExceptionAsync è posizionata all’interno di un blocco try-catch, non verrà rilevata l’eccezione al suo interno.

Pubblicato da

Andrea Merlin

Laureato in informatica, diversi corsi di specializzazione legati allo Sviluppo Software e alla Computer forensics. Appassionato di nuove tecnologie, amo la programmazione, la Business Intelligence e tematiche legate alla Privacy.Sempre alla ricerca di nuove idee, stimoli … e progetti da seguire!Amo trascorrere il tempo libero in Val Borbera, un piccolo angolo del Piemonte, in provincia di Alessandria.