Utilizzo della parola chiave async nella firma del metodo per restituire un’attività in un endpoint Web Api

Se volessi scrivere un’azione di api web non bloccante restituendo un object Task , potrei farlo con o senza usare la parola chiave async come tale:

Uso asincrono

 public async Task Get() { Func slowCall = () => { Thread.Sleep(2000); return Request.CreateResponse(HttpStatusCode.OK, "Hello world"); }; var task = Task.Factory.StartNew(slowCall); return await task; } 

Senza usare async

 public Task Get() { Func slowCall = () => { Thread.Sleep(2000); return Request.CreateResponse(HttpStatusCode.OK, "Hello world"); }; var task = Task.Factory.StartNew(slowCall); return task; } 

Entrambi funzionano correttamente. Tuttavia, ogni esempio che ho visto (online e nei libri) sulla scrittura di un’azione Web api che restituisce un’attività utilizza la parola chiave async . Certo, capisco che ti dà più flessibilità in quanto ti permette di controllare ciò che si desidera “attendere” e cosa no. Ma assumendo che la tua funzionalità possa essere efficacemente gestita in entrambi i modi,

  • C’è qualche vantaggio nell’usare un approccio rispetto all’altro?
  • Devo sempre usare la parola chiave async (e se sì perché)?
  • O è irrilevante?

La parola chiave async consente di utilizzare await nel metodo creando una macchina a stati. Se riesci a restituire un’attività asincrona senza usarla, puoi procedere e rimuoverla perché ha un sovraccarico (molto piccolo). Ricorda però che è utile solo in alcuni casi. Il tuo return await è uno di loro.

Un’altra differenza è come vengono gestite le eccezioni. Se c’è un’eccezione nella parte sincrona del metodo e viene contrassegnata come async l’eccezione verrà memorizzata nell’attività restituita. Senza la parola chiave l’eccezione verrebbe generata regolarmente. Per esempio in questo caso c’è una grande differenza:

 var task = Get(); // unhandled exception without async try { var result = await task; // handled exception with async } catch { } 

La mia raccomandazione è quella di utilizzare la parola chiave async anche quando non è assolutamente necessario *, perché la maggior parte degli sviluppatori non comprende la differenza e il valore nell’ottimizzazione è per lo più trascurabile.


* A meno che tu e i tuoi compagni di squadra non sappiate davvero cosa state facendo.

C’è un vantaggio nell’escludere l’ await e restituire direttamente l’ Task : le prestazioni. Non assegnerai né elaborerai il computer di stato che utilizza un metodo async . Vi sono, tuttavia, alcune sottili differenze in caso di eccezioni.

Nell’esempio asincrono, tutte le eccezioni generate verranno incluse in un’attività. Questo è generalmente ciò che la gente suppone accadrà quando chiamano un metodo di ritorno delle attività. Nell’esempio di sincronizzazione, le eccezioni verranno lanciate immediatamente dopo l’invocazione.

Ciò avrà anche un effetto sulla traccia dello stack dell’eccezione. Nell’esempio asincrono, mostrerà Get() . Nell’esempio di sincronizzazione, mostrerà il tuo delegato anonimo o, peggio ancora, alcune cazzate interne in Task.Factory.StartNew senza alcun riferimento effettivo al tuo codice attuale. Ciò può risultare un po ‘più difficile da eseguire il debug.