Async è in attesa di parole chiave equivalenti a un ContinueWith lambda?

Qualcuno potrebbe essere così gentile da confermare se ho capito correttamente la parola chiave Attendere Async? (Utilizzando la versione 3 del CTP)

Finora ho capito che inserire la parola chiave await prima di una chiamata di metodo essenzialmente fa 2 cose, A. Crea un ritorno immediato e B. Crea una “continuazione” che viene invocata al completamento del richiamo del metodo asincrono. In ogni caso la continuazione è il resto del blocco di codice per il metodo.

Quindi, quello che mi chiedo, sono questi due bit di codice tecnicamente equivalenti, e se è così, questo significa in sostanza che la parola chiave await è identica alla creazione di ContinueWith Lambda (Ie: è fondamentalmente una scorciatoia del compilatore per uno)? Se no, quali sono le differenze?

bool Success = await new POP3Connector( "mail.server.com", txtUsername.Text, txtPassword.Text).Connect(); // At this point the method will return and following code will // only be invoked when the operation is complete(?) MessageBox.Show(Success ? "Logged In" : "Wrong password"); 

VS

 (new POP3Connector( "mail.server.com", txtUsername.Text, txtPassword.Text ).Connect()) .ContinueWith((success) => MessageBox.Show(success.Result ? "Logged In" : "Wrong password")); 

L’idea generale è corretta – il resto del metodo viene trasformato in una continuazione di sorta.

Il post del blog “percorso veloce” contiene dettagli su come funziona la trasformazione del compilatore async / await .

Differenze, in cima alla mia testa:

La parola chiave await fa anche uso di un concetto di “contesto di pianificazione”. Il contesto di pianificazione è SynchronizationContext.Current se esiste, ricadendo su TaskScheduler.Current . La continuazione viene quindi eseguita nel contesto di pianificazione. Quindi una approssimazione più vicina sarebbe passare TaskScheduler.FromCurrentSynchronizationContext in ContinueWith , ricadendo su TaskScheduler.Current se necessario.

L’attuale implementazione async / await si basa sulla corrispondenza del pattern; usa uno schema “attendibile” che consente di attendere altre cose oltre ai compiti. Alcuni esempi sono le API asincrone WinRT, alcuni metodi speciali come Yield , osservabili Rx e speciali attese di socket che non colpiscono il GC con difficoltà . I compiti sono potenti, ma non sono gli unici attesi.

Viene in mente un’altra piccola differenza nitpicky: se l’attendibile è già completato, allora il metodo async non ritorna effettivamente in quel punto; continua in modo sincrono. Quindi è un po ‘come passare TaskContinuationOptions.ExecuteSynchronously , ma senza i problemi relativi allo stack.

È “essenzialmente” quello, ma il codice generato fa molto più di quello. Per molti più dettagli sul codice generato, consiglio vivamente la serie Eduasync di Jon Skeet:

http://codeblog.jonskeet.uk/category/eduasync/

In particolare, il post # 7 entra in ciò che viene generato (come da CTP 2) e perché, quindi probabilmente è un ottimo adattamento per quello che stai cercando al momento:

http://codeblog.jonskeet.uk/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method/

EDIT: Penso che sia probabile che sia più dettagliato di quello che stai cercando dalla domanda, ma se ti stai chiedendo come stanno le cose quando hai più attese nel metodo, questo è trattato nel post # 9 🙂

http://codeblog.jonskeet.uk/2011/05/30/eduasync-part-9-generated-code-for-multiple-awaits/