Come funziona Async and Await

Sto cercando di capire come funzionano Async e Await. Come il controllo viaggia nel programma. Ecco il codice che stavo cercando di capire.

public async Task MyMethod() { Task longRunningTask = LongRunningOperation(); //indeed you can do independent to the int result work here MySynchronousMethod(); //and now we call await on the task int result = await longRunningTask; //use the result Console.WriteLine(result); } public async Task LongRunningOperation() // assume we return an int from this long running operation { await Task.Delay(5000); //5 seconds delay return 1; } private void Button_Click_3(object sender, RoutedEventArgs e) { MyMethod(); } 

Quando si fa clic sul pulsante, viene chiamato MyMethod() e dal MyMethod LongRunningOperation() chiamato LongRunningOperation() e il completamento richiede 5 secondi. quindi la mia domanda è

  • Qual è il significato di questa linea

    Task longRunningTask = LongRunningOperation ();

  • cosa significa int result = await longRunningTask;

La linea sopra potrebbe essere impegnata e una linea che possiamo build come

 Task longRunningTask = await LongRunningOperation(); 

o

 int result = await longRunningTask; 

Per favore qualcuno può spiegarmi il codice di cui sopra che non mi è chiaro.

1) se longRunningOperation non è terminato ed è ancora in esecuzione, MyMethod () tornerà al suo metodo di chiamata, quindi il thread principale non verrà bloccato. Quando viene eseguito longRunningOperation, un thread dal ThreadPool (può essere un qualsiasi thread) tornerà a MyMethod () al suo stato precedente e continuerà l’esecuzione (in questo caso stampando il risultato sulla console).

Un secondo caso sarebbe che longRunningOperation ha già terminato la sua esecuzione e il risultato è disponibile. Quando si raggiunge l’attesa longRunningOperation, il compilatore sa che ha il risultato e continuerà a eseguire il codice sullo stesso thread. (in questo caso, stampa dei risultati su console).

il punto 1 non mi è affatto chiaro come l’affermazione ” if the longRunningOperation hasn't finished and is still running, MyMethod() will return to its calling method

se ansible, spiega il punto uno in maggiore dettaglio. Grazie

Ho una presentazione async sul mio blog che potresti trovare utile.

Questo codice:

 int result = await LongRunningOperation(); 

è essenzialmente lo stesso di questo codice:

 Task resultTask = LongRunningOperation(); int result = await resultTask; 

Quindi, sì, LongRunningOperation viene richiamato direttamente da tale metodo.

Quando l’operatore await è passato a un’attività già completata, estrae il risultato e continua a eseguire il metodo (in modo sincrono).

Quando l’operatore await viene passato un compito incompleto (ad esempio, l’attività restituita da LongRunningOperation non sarà completa), quindi per impostazione predefinita, await il contesto corrente e restituirà un’attività incompleta dal metodo.

Successivamente, quando l’attività await completa, il resto del metodo è pianificato per essere eseguito in quel contesto.

Questo “contesto” è SynchronizationContext.Current meno che non sia null , nel qual caso è TaskScheduler.Current . Se si esegue questo in un’app Console, il contesto è in genere il contesto del pool di thread, quindi il metodo async riprenderà l’esecuzione in un thread del pool di thread. Tuttavia, se si esegue lo stesso metodo su un thread dell’interfaccia utente, il contesto è un contesto dell’interfaccia utente e il metodo async riprenderà l’esecuzione sul thread dell’interfaccia utente.

Mi è stato insegnato a riguardo nel modo seguente, ho trovato una spiegazione abbastanza chiara e concisa:

 //this is pseudocode async Method() { code; code; await something; moreCode; } 

Quando viene invocato Method , esegue il suo contenuto ( code; linee) per await something; . A quel punto, something; viene licenziato e il metodo termina come un return; era li.

something; fa ciò di cui ha bisogno e poi ritorna.

Quando something; ritorna, l’esecuzione ritorna al Method e procede dall’attesa in poi, eseguendo moreCode;

In un modo ancora più schematico, ecco cosa succede:

  1. Il metodo è invocato
  2. code; viene eseguito
  3. something; viene eseguito, il stream ritorna al punto in cui è stato richiamato il Method
  4. l’esecuzione continua con ciò che viene dopo l’invocazione del Method
  5. quando something; ritorni, ritorni di stream all’interno del Method
  6. moreCode; viene eseguito e il Method stesso termina (sì, potrebbe esserci qualcos’altro in await su di esso, e così via e così via)

Dietro le quinte il compilatore C # converte il tuo codice in una macchina a stati. Genera molto più codice in modo che dietro le quinte ogni volta che un’attività di attesa o un’azione asincrona viene completata, continuerà l’esecuzione dal punto in cui era stata interrotta. In termini di domanda, ogni volta che l’azione asincrona è terminata, il metodo asincrono verrà richiamato sul thread chiamante quando avvii originariamente la chiamata al metodo asincrono. Ad esempio, eseguirà il codice sul thread su cui hai iniziato. Quindi l’azione asincrona verrà eseguita su un thread Attività, quindi il risultato verrà restituito sul thread in cui il metodo è stato originariamente richiamato e continua ad essere eseguito.

attendi otterrà il valore dall’azione Task o async e “unbox” dall’attività quando viene restituita l’esecuzione, in questo caso lo inserirà automaticamente nel valore int, quindi non è necessario archiviare l’attività.

Il tuo codice ha il problema di attendersi su LongRunningTask (), è molto probabile che tu voglia semplicemente restituire il metodo di attività lungo senza async, quindi fare in modo che MyMethod esegua l’attesa.

int value = attendi LongWaitingTask ()

http://www.codeproject.com/Articles/535635/Async-Await-and-the-Generated-StateMachine

È un requisito dei metodi asincroni che si restituisce un’attività o vuoto.

È ansible modificarlo in modo che quando si ritorna dall’esecuzione dell’attività asincrona verrà eseguito il codice rimanente sul thread l’attività asincrona è stata eseguita utilizzando http://msdn.microsoft.com/en-us/library/system. threading.tasks.task.configureawait (v = vs.110) .aspx