2015-12-31 15 views
11

Sto cercando di trovare le migliori pratiche per uno dei miei progetti. È una tipica applicazione WPF con un'interfaccia utente che visualizza un elenco di elementi e un servizio dati che restituisce il risultato.Async await vs GetAwaiter(). GetResult() e callback

Chiamiamo il servizio in modo asincrono in modo da non bloccare l'interfaccia utente. Abbiamo 2 opzioni di fronte a noi:

  1. Uso Async attendere parole chiave Questo richiede segnando tutti i metodi asincroni da fare clic sul pulsante fino a livello di servizio (classe sul lato client che effettua la chiamata HTTP al server) e qualsiasi metodo in mezzo. Questo approccio funziona benissimo quindi il problema della propagazione asincrona ovunque

  2. Usa attendente e richiamata In questo approccio il client dell'interfaccia utente chiama il livello di servizio e passa una richiamata al livello di servizio, il livello di servizio avvolge la chiamata http al server in un'attività e utilizzare GetAwaiter(). GetResult(), al termine della chiamata http richiama il callback passato dal client dell'interfaccia utente. In questo caso, nessun metodo deve essere contrassegnato come asincrono, ma non è realmente sicuro dell'uso di GetAwaiter()

    Task.Run (async() => // attende la chiamata http, richiama callback) .GetAwaiter(). GetResult ();

Sto solo cercando di scoprire che è un approccio migliore e se ci sono alcuni problemi con entrambi gli approcci che avrei dovuto essere a conoscenza

+1

Sono abbastanza sicuro che il secondo approccio può portare a serrature morte una volta ogni tanto. Lo so perché ho affrontato qualcosa di simile nello sviluppo con Windows Universal. – Felype

+0

C'è anche la questione delle eccezioni. Conosco un'implementazione asincrona completa, alla fine si ottiene la funzione 'AggregateException', ma non ho idea di cosa succede alle eccezioni nel metodo' GetAwaiter' – Eris

+0

@Eris Quando si attende non si ottiene un 'AggregateException'. Ottieni l'eccezione interiore. Lo stesso succede con 'GetResult'. – i3arnon

risposta

16

Si consiglia di utilizzare i async e await parole chiave tutta la strada fino , o non dovresti usare async affatto.

La seconda opzione non è realmente asincrona. Si chiama un'operazione asincrona e si blocca su di esso in modo sincrono con task.GetAwaiter().GetResult(). Oltre ad essere molto complicato, non è asincrono e può portare a deadlock.

+0

Hai altre informazioni di background sul motivo per cui può causare deadlock? Ho sperimentato anche questo, ma sto cercando informazioni più approfondite sul perché questo accada o su come funziona. –

+2

@FrederikGheysels http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – i3arnon

+0

Sembra un ottimo consiglio, eccetto che sono bloccato con questa API da Azure Active Directory (TokenCache) che richiede operazioni sincrone. Non è possibile tornare da "BeforeAccessNotification" finché non si legge la cache e non è possibile tornare da "AfterAccessNotification" finché non si scrive la cache. Qual è il tuo consiglio quando sei costretto a utilizzare un'API sincrona e devi accedere a un file? –