Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
È possibile scrivere e gestire programmi asincroni più facilmente usando le Async
parole chiave e Await
. Tuttavia, i risultati potrebbero sorprendere se non si capisce come funziona il programma. Questo argomento analizza il flusso del controllo tramite un semplice programma asincrono per mostrare quando il controllo passa da un metodo a un altro e quali informazioni vengono trasferite ogni volta.
Annotazioni
Le Async
parole chiave e Await
sono state introdotte in Visual Studio 2012.
In generale, si contrassegnano i metodi che contengono codice asincrono con il modificatore Async . In un metodo contrassegnato con un modificatore asincrono, è possibile usare un operatore Await (Visual Basic) per specificare dove il metodo viene sospeso per attendere il completamento di un processo asincrono chiamato. Per altre informazioni, vedere Programmazione asincrona con Async e Await (Visual Basic).
Nell'esempio seguente vengono utilizzati metodi asincroni per scaricare il contenuto di un sito Web specificato come stringa e per visualizzare la lunghezza della stringa. L'esempio contiene i due metodi seguenti.
startButton_Click
, che chiamaAccessTheWebAsync
e visualizza il risultato.AccessTheWebAsync
, che scarica il contenuto di un sito Web come stringa e restituisce la lunghezza della stringa.AccessTheWebAsync
usa un metodo asincrono HttpClient , GetStringAsync(String), per scaricare il contenuto.
Le linee di visualizzazione numerate vengono visualizzate in punti strategici in tutto il programma per comprendere come viene eseguito il programma e spiegare cosa accade in ogni punto contrassegnato. Le linee di visualizzazione sono etichettate da "ONE" a "SIX". Le etichette rappresentano l'ordine in cui il programma raggiunge queste righe di codice.
Il codice seguente illustra una struttura del programma.
Class MainWindow
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) Handles StartButton.Click
' ONE
Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
' FOUR
Dim contentLength As Integer = Await getLengthTask
' SIX
ResultsTextBox.Text &=
vbCrLf & $"Length of the downloaded string: {contentLength}." & vbCrLf
End Sub
Async Function AccessTheWebAsync() As Task(Of Integer)
' TWO
Dim client As HttpClient = New HttpClient()
Dim getStringTask As Task(Of String) =
client.GetStringAsync("https://learn.microsoft.com")
' THREE
Dim urlContents As String = Await getStringTask
' FIVE
Return urlContents.Length
End Function
End Class
Ognuna delle posizioni etichettate, da "ONE" a "SIX", visualizza informazioni sullo stato corrente del programma. Viene generato l'output seguente:
ONE: Entering startButton_Click.
Calling AccessTheWebAsync.
TWO: Entering AccessTheWebAsync.
Calling HttpClient.GetStringAsync.
THREE: Back in AccessTheWebAsync.
Task getStringTask is started.
About to await getStringTask & return a Task<int> to startButton_Click.
FOUR: Back in startButton_Click.
Task getLengthTask is started.
About to await getLengthTask -- no caller to return to.
FIVE: Back in AccessTheWebAsync.
Task getStringTask is complete.
Processing the return statement.
Exiting from AccessTheWebAsync.
SIX: Back in startButton_Click.
Task getLengthTask is finished.
Result from AccessTheWebAsync is stored in contentLength.
About to display contentLength and exit.
Length of the downloaded string: 33946.
Configurare il programma
È possibile scaricare il codice usato da questo argomento da MSDN oppure compilarlo manualmente.
Annotazioni
Per eseguire l'esempio, è necessario che Nel computer sia installato Visual Studio 2012 o versione successiva e .NET Framework 4.5 o versione successiva.
Scaricare il programma
È possibile scaricare l'applicazione per questo argomento da Async Sample: Control Flow in Async Programs (Esempio asincrono: Flusso di controllo nei programmi asincroni). I passaggi seguenti aprono ed eseguono il programma.
Decomprimere il file scaricato e quindi avviare Visual Studio.
Sulla barra dei menu scegliere File, Apri, Progetto/Soluzione.
Passare alla cartella che contiene il codice di esempio decompresso, aprire il file della soluzione (.sln) e quindi scegliere la chiave F5 per compilare ed eseguire il progetto.
Creare il programma manualmente
Il progetto Windows Presentation Foundation (WPF) seguente contiene l'esempio di codice per questo argomento.
Per eseguire il progetto, seguire questa procedura:
Avvia Visual Studio.
Nella barra dei menu scegliere File, Nuovo, Progetto.
Verrà visualizzata la finestra di dialogo Nuovo progetto .
Nel riquadro Modelli installati scegliere Visual Basic e quindi scegliere Applicazione WPF dall'elenco dei tipi di progetto.
Immettere
AsyncTracer
come nome del progetto e quindi scegliere il pulsante OK .Il nuovo progetto verrà visualizzato in Esplora soluzioni.
Nell'Editor di codice di Visual Studio scegliere la scheda MainWindow.xaml .
Se la scheda non è visibile, aprire il menu di scelta rapida per MainWindow.xaml in Esplora soluzioni e quindi scegliere Visualizza codice.
Nella visualizzazione XAML di MainWindow.xaml sostituire il codice con il codice seguente.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="MainWindow" Title="Control Flow Trace" Height="350" Width="525"> <Grid> <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="221,10,0,0" VerticalAlignment="Top" Width="75"/> <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Bottom" Width="510" Height="265" FontFamily="Lucida Console" FontSize="10" VerticalScrollBarVisibility="Visible" d:LayoutOverrides="HorizontalMargin"/> </Grid> </Window>
Una finestra semplice che contiene una casella di testo e un pulsante viene visualizzato nella visualizzazione Progettazione di MainWindow.xaml.
Aggiungere un riferimento per System.Net.Http.
In Esplora soluzioni aprire il menu di scelta rapida per MainWindow.xaml.vb e quindi scegliere Visualizza codice.
In MainWindow.xaml.vb sostituire il codice con il codice seguente.
' Add an Imports statement and a reference for System.Net.Http. Imports System.Net.Http Class MainWindow Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) Handles StartButton.Click ' The display lines in the example lead you through the control shifts. ResultsTextBox.Text &= "ONE: Entering StartButton_Click." & vbCrLf & " Calling AccessTheWebAsync." & vbCrLf Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync() ResultsTextBox.Text &= vbCrLf & "FOUR: Back in StartButton_Click." & vbCrLf & " Task getLengthTask is started." & vbCrLf & " About to await getLengthTask -- no caller to return to." & vbCrLf Dim contentLength As Integer = Await getLengthTask ResultsTextBox.Text &= vbCrLf & "SIX: Back in StartButton_Click." & vbCrLf & " Task getLengthTask is finished." & vbCrLf & " Result from AccessTheWebAsync is stored in contentLength." & vbCrLf & " About to display contentLength and exit." & vbCrLf ResultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, contentLength) End Sub Async Function AccessTheWebAsync() As Task(Of Integer) ResultsTextBox.Text &= vbCrLf & "TWO: Entering AccessTheWebAsync." ' Declare an HttpClient object. Dim client As HttpClient = New HttpClient() ResultsTextBox.Text &= vbCrLf & " Calling HttpClient.GetStringAsync." & vbCrLf ' GetStringAsync returns a Task(Of String). Dim getStringTask As Task(Of String) = client.GetStringAsync("https://learn.microsoft.com") ResultsTextBox.Text &= vbCrLf & "THREE: Back in AccessTheWebAsync." & vbCrLf & " Task getStringTask is started." ' AccessTheWebAsync can continue to work until getStringTask is awaited. ResultsTextBox.Text &= vbCrLf & " About to await getStringTask & return a Task(Of Integer) to StartButton_Click." & vbCrLf ' Retrieve the website contents when task is complete. Dim urlContents As String = Await getStringTask ResultsTextBox.Text &= vbCrLf & "FIVE: Back in AccessTheWebAsync." & vbCrLf & " Task getStringTask is complete." & vbCrLf & " Processing the return statement." & vbCrLf & " Exiting from AccessTheWebAsync." & vbCrLf Return urlContents.Length End Function End Class
Scegliere il tasto F5 per eseguire il programma e quindi scegliere il pulsante Start .
Verrà visualizzato l'output seguente:
ONE: Entering startButton_Click. Calling AccessTheWebAsync. TWO: Entering AccessTheWebAsync. Calling HttpClient.GetStringAsync. THREE: Back in AccessTheWebAsync. Task getStringTask is started. About to await getStringTask & return a Task<int> to startButton_Click. FOUR: Back in startButton_Click. Task getLengthTask is started. About to await getLengthTask -- no caller to return to. FIVE: Back in AccessTheWebAsync. Task getStringTask is complete. Processing the return statement. Exiting from AccessTheWebAsync. SIX: Back in startButton_Click. Task getLengthTask is finished. Result from AccessTheWebAsync is stored in contentLength. About to display contentLength and exit. Length of the downloaded string: 33946.
Traccia il programma
Passaggi uno e due
Le prime due righe di visualizzazione tracciano il percorso come startButton_Click
chiama AccessTheWebAsync
e AccessTheWebAsync
chiama il metodo HttpClientasincrono GetStringAsync(String) . L'immagine seguente illustra le chiamate tra i metodi.
Il tipo restituito di AccessTheWebAsync
e client.GetStringAsync
è Task<TResult>. Per AccessTheWebAsync
, TResult è un numero intero. Per GetStringAsync
, TResult è una stringa. Per altre informazioni sui tipi restituiti dal metodo asincrono, vedere Tipi restituiti asincroni (Visual Basic).For more information about async method return types, see Async Return Types (Visual Basic).
Un metodo asincrono che restituisce un'attività restituisce un'istanza dell'attività quando il controllo torna al chiamante. Il controllo ritorna da un metodo asincrono al chiamante quando si incontra un operatore Await
nel metodo chiamato o quando il metodo chiamato termina. Le righe di visualizzazione etichettate da "THREE" a "SIX" documentano questa parte del processo.
Passaggio TRE
In AccessTheWebAsync
viene chiamato il metodo GetStringAsync(String) asincrono per scaricare il contenuto della pagina Web di destinazione. Il controllo restituisce da client.GetStringAsync
a AccessTheWebAsync
quando client.GetStringAsync
viene restituito.
Il client.GetStringAsync
metodo restituisce un'attività di stringa assegnata alla getStringTask
variabile in AccessTheWebAsync
. La riga seguente nel programma di esempio mostra la chiamata a client.GetStringAsync
e l'assegnazione.
Dim getStringTask As Task(Of String) = client.GetStringAsync("https://learn.microsoft.com")
È possibile considerare l'attività come una promessa di client.GetStringAsync
di produrre una stringa effettiva in futuro. Nel frattempo, se AccessTheWebAsync
ha del lavoro che non dipende dalla stringa promessa da client.GetStringAsync
, quel lavoro può continuare mentre client.GetStringAsync
aspetta. Nell'esempio, le righe di output seguenti, etichettate come "THREE", rappresentano l'opportunità di eseguire operazioni indipendenti
THREE: Back in AccessTheWebAsync.
Task getStringTask is started.
About to await getStringTask & return a Task<int> to startButton_Click.
La dichiarazione seguente sospende lo stato di avanzamento in AccessTheWebAsync
quando getStringTask
è atteso.
Dim urlContents As String = Await getStringTask
L'immagine seguente mostra il flusso di controllo da client.GetStringAsync
all'assegnazione a getStringTask
e dalla creazione di getStringTask
all'applicazione di un operatore Await.
L'espressione await si sospende AccessTheWebAsync
finché client.GetStringAsync
non restituisce. Nel frattempo, il controllo torna al chiamante di AccessTheWebAsync
, startButton_Click
.
Annotazioni
In genere, si attende immediatamente la chiamata a un metodo asincrono. Ad esempio, l'assegnazione seguente potrebbe sostituire il codice precedente che crea e quindi attende getStringTask
: Dim urlContents As String = Await client.GetStringAsync("https://learn.microsoft.com")
In questo argomento l'operatore await viene applicato in un secondo momento per contenere le righe di output che contrassegnano il flusso del controllo attraverso il programma.
Passaggio QUATTRO
Il tipo restituito dichiarato di AccessTheWebAsync
è Task(Of Integer)
. Pertanto, quando AccessTheWebAsync
viene sospeso, restituisce un'attività di integer a startButton_Click
. È necessario comprendere che l'attività restituita non è getStringTask
. L'attività restituita è una nuova attività di integer che rappresenta ciò che rimane da eseguire nel metodo sospeso, AccessTheWebAsync
. L'attività è una promessa da AccessTheWebAsync
di produrre un numero intero al suo completamento.
L'istruzione seguente assegna questa attività alla getLengthTask
variabile .
Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
Come in AccessTheWebAsync
, startButton_Click
può continuare con il lavoro che non dipende dai risultati dell'attività asincrona (getLengthTask
) fino a quando l'attività non è attesa. Le righe di output seguenti rappresentano il lavoro.
FOUR: Back in startButton_Click.
Task getLengthTask is started.
About to await getLengthTask -- no caller to return to.
L'avanzamento in startButton_Click
è sospeso attendendo getLengthTask
. L'istruzione di assegnazione seguente sospende startButton_Click
fino al completamento di AccessTheWebAsync
.
Dim contentLength As Integer = Await getLengthTask
Nell'illustrazione seguente, le frecce mostrano il flusso di controllo dall'espressione await in AccessTheWebAsync
all'assegnazione di un valore a getLengthTask
, seguito dall'elaborazione normale in startButton_Click
fino a quando getLengthTask
non viene atteso.
Passaggio CINQUE
Quando client.GetStringAsync
segnala che è completa, l'elaborazione in AccessTheWebAsync
viene rilasciata dalla sospensione e può continuare oltre l'istruzione await. Le righe di output seguenti rappresentano la ripresa dell'elaborazione:
FIVE: Back in AccessTheWebAsync.
Task getStringTask is complete.
Processing the return statement.
Exiting from AccessTheWebAsync.
L'operando dell'istruzione return, urlContents.Length
, viene archiviato nell'attività che AccessTheWebAsync
restituisce. L'espressione await recupera tale valore da getLengthTask
in startButton_Click
.
L'immagine seguente mostra il trasferimento del controllo dopo il completamento di client.GetStringAsync
(e getStringTask
).
AccessTheWebAsync
viene eseguito fino al completamento, e il controllo ritorna a startButton_Click
, che è in attesa del completamento.
Passaggio SEI
Quando AccessTheWebAsync
segnala che è stata completata, l'elaborazione può continuare oltre l'istruzione await in startButton_Async
. Infatti, il programma non ha più nulla da fare.
Le righe di output seguenti rappresentano la ripresa dell'elaborazione in startButton_Async
:
SIX: Back in startButton_Click.
Task getLengthTask is finished.
Result from AccessTheWebAsync is stored in contentLength.
About to display contentLength and exit.
L'espressione await recupera dal getLengthTask
valore intero che è l'operando dell'istruzione return in AccessTheWebAsync
. L'istruzione seguente assegna tale valore alla contentLength
variabile .
Dim contentLength As Integer = Await getLengthTask
L'immagine seguente mostra il ritorno del controllo da AccessTheWebAsync
a startButton_Click
.