Le risposte di SLaks e Killercam sono buone; Ho pensato di aggiungere solo un po 'più di contesto.
La tua prima domanda riguarda essenzialmente quali metodi possono essere contrassegnati async.
Un metodo contrassegnato come asyncpuò restituire void, Taskoppure Task<T>. Quali sono le differenze tra loro?
È Task<T>possibile attendere un metodo asincrono di ritorno e quando l'attività viene completata, viene offerto un T.
È Taskpossibile attendere un metodo asincrono di ritorno e al termine dell'attività è pianificata l'esecuzione della continuazione dell'attività.
Un voidmetodo asincrono ritorno non può essere atteso; è un metodo "spara e dimentica". Funziona in modo asincrono e non hai modo di dire quando è fatto. Questo è più che un po 'strano; come dice SLaks, normalmente lo faresti solo quando crei un gestore di eventi asincrono. L'evento si attiva, il gestore esegue; nessuno "attenderà" l'attività restituita dal gestore eventi perché i gestori eventi non restituiscono attività e, anche se lo facessero, quale codice userebbe l'attività per qualcosa? Di solito non è il codice utente che trasferisce il controllo al gestore.
La tua seconda domanda, in un commento, riguarda essenzialmente ciò che può essere awaited:
Quali tipi di metodi possono essere modificati await? È possibile modificare un metodo di ritorno del vuoto await?
No, non è possibile attendere un metodo di ritorno del vuoto. Il compilatore si traduce await M()in una chiamata a M().GetAwaiter(), dove GetAwaiterpotrebbe essere un metodo di istanza o un metodo di estensione. Il valore atteso deve essere uno per il quale è possibile ottenere un cameriere; chiaramente un metodo di ritorno del vuoto non produce un valore da cui è possibile ottenere un cameriere.
Taski metodi di ritorno possono produrre valori attendibili. Prevediamo che terze parti vorranno creare le proprie implementazioni di Taskoggetti simili che possono essere attesi e che sarete in grado di aspettarli. Tuttavia, non ti sarà permesso di dichiarare asyncmetodi che restituiscono altro che void, Tasko Task<T>.
(AGGIORNAMENTO: la mia ultima frase potrebbe essere falsata da una versione futura di C #; esiste una proposta per consentire tipi di ritorno diversi dai tipi di attività per i metodi asincroni.)
(AGGIORNAMENTO: la funzionalità sopra menzionata è arrivata a C # 7.)