Opertore Await (Visual Basic)
Applicare l'operatore Await
a un operando in un metodo o in un'espressione lambda asincroni per sospendere l'esecuzione del metodo finché l'attività di cui si è in attesa non viene completata. L'attività rappresenta il lavoro attualmente in fase di esecuzione.
Il metodo in cui Await
viene usato deve avere un modificatore Async. Tale metodo, definito usando il modificatore Async
e contenente di solito una o più espressioni Await
, viene denominato metodo asincrono.
Nota
Le parole chiave Async
e Await
sono state introdotte in Visual Studio 2012. Per un'introduzione alla programmazione asincrona, vedere Programmazione asincrona con async e await.
Solitamente l'attività a cui si applica l'operatore Await
è il valore restituito da una chiamata a un metodo che implementa il modello asincrono basato su attività, ovvero Task o Task<TResult>.
Nel seguente codice, l'elemento HttpClient del metodo GetByteArrayAsync restituisce getContentsTask
, un elemento Task(Of Byte())
. L'attività è una promessa di produrre la matrice di byte effettiva una volta completata l'operazione. L'operatore Await
viene applicato a getContentsTask
per sospendere l'esecuzione in SumPageSizesAsync
fino al completamento di getContentsTask
. Nel frattempo, il controllo viene restituito al chiamante di SumPageSizesAsync
. Quando getContentsTask
termina, l'espressione Await
restituisce una matrice di byte.
Private Async Function SumPageSizesAsync() As Task
' To use the HttpClient type in desktop apps, you must include a using directive and add a
' reference for the System.Net.Http namespace.
Dim client As HttpClient = New HttpClient()
' . . .
Dim getContentsTask As Task(Of Byte()) = client.GetByteArrayAsync(url)
Dim urlContents As Byte() = Await getContentsTask
' Equivalently, now that you see how it works, you can write the same thing in a single line.
'Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
' . . .
End Function
Importante
Per l'esempio completo, vedere Procedura dettagliata: accesso al Web con async e await. È possibile scaricare l'esempio dal browser di esempio .NET. Il codice di esempio si trova nel progetto SerialAsyncExample.
Se Await
viene applicato al risultato di una chiamata a un metodo che restituisce un elemento Task(Of TResult)
, il tipo dell'espressione Await
è TResult. Se Await
viene applicato al risultato di una chiamata a un metodo che restituisce Task
, l'espressione Await
non restituisce un valore. Nell'esempio che segue viene illustrata la differenza.
' Await used with a method that returns a Task(Of TResult).
Dim result As TResult = Await AsyncMethodThatReturnsTaskTResult()
' Await used with a method that returns a Task.
Await AsyncMethodThatReturnsTask()
Un'espressione o un'istruzione Await
non blocca il thread su cui è in esecuzione. Comporta invece la registrazione, tramite il compilatore, della parte restante del metodo asincrono, dopo l'espressione Await
, come continuazione dell'attività di cui si è in attesa. Il controllo quindi viene restituito al chiamante del metodo asincrono. Al termine dell'attività, ne richiama la continuazione e l'esecuzione del metodo asincrono riprende da dove era stata interrotta.
Un'espressione Await
può trovarsi solo nel corpo di un metodo che la contiene o di un'espressione lambda contrassegnata da un modificatore Async
. Il termine Await funge da parola chiave solo in tale contesto. Altrove, viene interpretata come identificatore. All'interno del metodo Async
o dell'espressione lambda, un'espressione Await
non può trovarsi in un'espressione di query, nei blocchi Catch
o Finally
di un'istruzione Try... Catch... Finally, nell'espressione di una variabile di controllo di un ciclo For
o For Each
oppure nel corpo di un'istruzione SyncLock.
Eccezioni
La maggior parte dei metodi asincroni restituisce Task o Task<TResult>. Le proprietà dell'attività restituita contengono informazioni sullo stato e sulla cronologia, ad esempio se l'attività è stata completata, se il metodo asincrono ha generato un'eccezione o è stato annullato e il risultato finale. L'operatore Await
accede a tali proprietà.
Se si è in attesa di un metodo asincrono che restituisce un'attività che genera un'eccezione, l'operatore Await
genera di nuovo l'eccezione.
Se si è in attesa di un metodo asincrono che restituisce un'attività che è stato annullato, tramite l'operatore Await
viene rigenerata un'eccezione OperationCanceledException.
Una singola attività in uno stato di errore può rispecchiare più eccezioni. Ad esempio, l'attività può essere il risultato di una chiamata a Task.WhenAll. Quando si attende tale attività, l'operazione await rigenera solo una delle eccezioni. Tuttavia, non è possibile prevedere quale delle eccezioni verrà rigenerata.
Per esempi di gestione degli errori nei metodi asincroni, vedere l'istruzione Try... Catch... Finally.
Esempio
Il seguente esempio di Windows Form illustra l'uso di Await
in un metodo asincrono, WaitAsynchronouslyAsync
. Contrastare il comportamento di tale metodo con il comportamento di WaitSynchronously
. Senza un operatore Await
, WaitSynchronously
viene eseguito in modo sincrono nonostante l'uso del modificatore Async
nella definizione e di una chiamata a Thread.Sleep nel corpo.
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Call the method that runs asynchronously.
Dim result As String = Await WaitAsynchronouslyAsync()
' Call the method that runs synchronously.
'Dim result As String = Await WaitSynchronously()
' Display the result.
TextBox1.Text &= result
End Sub
' The following method runs asynchronously. The UI thread is not
' blocked during the delay. You can move or resize the Form1 window
' while Task.Delay is running.
Public Async Function WaitAsynchronouslyAsync() As Task(Of String)
Await Task.Delay(10000)
Return "Finished"
End Function
' The following method runs synchronously, despite the use of Async.
' You cannot move or resize the Form1 window while Thread.Sleep
' is running because the UI thread is blocked.
Public Async Function WaitSynchronously() As Task(Of String)
' Import System.Threading for the Sleep method.
Thread.Sleep(10000)
Return "Finished"
End Function