Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Możesz łatwiej pisać i zarządzać programami asynchronicznymi przy użyciu słów kluczowych Async i Await. Jednak wyniki mogą cię zaskoczyć, jeśli nie rozumiesz sposobu działania programu. W tym temacie śledzi się przepływ sterowania w prostym programie asynchronicznym, aby pokazać, kiedy przepływ sterowania przechodzi z jednej metody do innej i jakie informacje są przesyłane za każdym razem.
Uwaga / Notatka
Słowa kluczowe Async i Await zostały wprowadzone w programie Visual Studio 2012.
Ogólnie rzecz biorąc, metody zawierające kod asynchroniczny są oznaczane modyfikatorem asynchronicznym. W metodzie oznaczonej modyfikatorem asynchronicznym można użyć operatora Await (Visual Basic), aby określić, gdzie metoda wstrzymuje się czekać na ukończenie wywoływanego procesu asynchronicznego. Aby uzyskać więcej informacji, zobacz Asynchroniczne programowanie za pomocą Async i Await (Visual Basic).
W poniższym przykładzie użyto metod asynchronicznych, aby pobrać zawartość określonej witryny internetowej jako ciąg i wyświetlić długość ciągu. Przykład zawiera następujące dwie metody.
startButton_Click, który wywołujeAccessTheWebAsynci wyświetla wynik.AccessTheWebAsync, który pobiera zawartość witryny internetowej jako ciąg i zwraca długość ciągu.AccessTheWebAsyncużywa asynchronicznej metody HttpClient do pobierania zawartości za pomocą GetStringAsync(String).
Ponumerowane linie wyświetlania są wyświetlane w punktach strategicznych w całym programie, aby ułatwić zrozumienie sposobu działania programu i wyjaśnienie, co się dzieje w każdym punkcie oznaczonym. Linie wyświetlania są oznaczone etykietą "ONE" do "SIX". Etykiety reprezentują kolejność, w jakiej program osiąga te linie kodu.
Poniższy kod przedstawia konspekt programu.
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
Każda z oznaczonych etykietami lokalizacji "ONE" do "SIX" wyświetla informacje o bieżącym stanie programu. Generowane są następujące dane wyjściowe:
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.
Konfigurowanie programu
Możesz pobrać kod używany w tym temacie z witryny MSDN lub utworzyć go samodzielnie.
Uwaga / Notatka
Aby uruchomić przykład, na komputerze musi być zainstalowany program Visual Studio 2012 lub nowszy oraz program .NET Framework 4.5 lub nowszy.
Pobieranie programu
Aplikację dla tego tematu można pobrać z async Sample: Control Flow in Async Programs (Przykład asynchroniczny: przepływ sterowania w programach asynchronicznych). Poniższe kroki otwierają i uruchamiają program.
Rozpakuj pobrany plik, a następnie uruchom program Visual Studio.
Na pasku menu wybierz pozycję Plik, Otwórz, Projekt/Rozwiązanie.
Przejdź do folderu zawierającego rozpakowany przykładowy kod, otwórz plik rozwiązania (.sln), a następnie wybierz klucz F5 do skompilowania i uruchomienia projektu.
Samodzielne tworzenie programu
Poniższy projekt Windows Presentation Foundation (WPF) zawiera przykład kodu dla tego tematu.
Aby uruchomić projekt, wykonaj następujące kroki:
Uruchom program Visual Studio.
Na pasku menu wybierz pozycję Plik, Nowy, Projekt.
Zostanie otwarte okno dialogowe Nowy projekt .
W okienku Zainstalowane szablony wybierz pozycję Visual Basic, a następnie wybierz pozycję Aplikacja WPF z listy typów projektów.
Wprowadź
AsyncTracerjako nazwę projektu, a następnie wybierz przycisk OK .Nowy projekt zostanie wyświetlony w Eksploratorze rozwiązań.
W edytorze programu Visual Studio Code wybierz kartę MainWindow.xaml .
Jeśli karta nie jest widoczna, otwórz menu skrótów dla pliku MainWindow.xaml w Eksploratorze rozwiązań, a następnie wybierz pozycję Wyświetl kod.
W widoku XAML pliku MainWindow.xaml zastąp kod następującym kodem.
<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>W widoku Projekt MainWindow.xaml pojawi się proste okno zawierające pole tekstowe i przycisk.
Dodaj odwołanie dla elementu System.Net.Http.
W Eksploratorze rozwiązań otwórz menu skrótów dla MainWindow.xaml.vb, a następnie wybierz pozycję Wyświetl kod.
W MainWindow.xaml.vb zastąp kod następującym kodem.
' 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 ClassWybierz F5, aby uruchomić program, a następnie wybierz przycisk Uruchom .
Powinny zostać wyświetlone następujące dane wyjściowe:
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.
Śledzenie programu
Kroki JEDEN i DWA
Dwa pierwsze wiersze wyświetlania śledzą ścieżkę, gdy startButton_Click wywołuje AccessTheWebAsync, a AccessTheWebAsync wywołuje asynchroniczną metodę HttpClientGetStringAsync(String). Poniższa ilustracja pokazuje wywołania między metodami.
Zwracany typ parametru AccessTheWebAsync i client.GetStringAsync ma wartość Task<TResult>. W przypadku funkcji AccessTheWebAsync, TResult jest liczbą całkowitą. W przypadku GetStringAsync, TResult jest ciągiem znaków. Aby uzyskać więcej informacji na temat typów zwracanych metod asynchronicznych, zobacz Async Return Types (Visual Basic).
Metoda asynchroniczna zwracająca obiekt Task zwraca jego instancję, gdy kontrola powraca do obiektu wywołującego. Sterowanie powraca z metody asynchronicznej do obiektu wywołującego, gdy napotkany zostanie operator Await w wywoływanej metodzie lub po zakończeniu wywoływanej metody. Linie wyświetlacza oznaczone etykietami od "TRZY" do "SZEŚĆ" śledzą tę część procesu.
Krok TRZECI
W AccessTheWebAsync wywoływana jest metoda GetStringAsync(String) asynchroniczna w celu pobrania zawartości docelowej strony internetowej. Kontrolka powraca z client.GetStringAsync do AccessTheWebAsync , gdy client.GetStringAsync zwraca.
Metoda client.GetStringAsync zwraca zadanie ciągu przypisanego do zmiennej getStringTask w pliku AccessTheWebAsync. W poniższym wierszu przykładowego programu pokazano wywołanie funkcji client.GetStringAsync oraz przypisanie.
Dim getStringTask As Task(Of String) = client.GetStringAsync("https://learn.microsoft.com")
Zadanie można traktować jako obietnicę client.GetStringAsync do ostatecznego wytworzenia rzeczywistego ciągu. W międzyczasie, jeśli AccessTheWebAsync ma pracę do wykonania, która nie zależy od obiecanego ciągu z client.GetStringAsync, ta praca może być kontynuowana, podczas gdy client.GetStringAsync oczekuje. W tym przykładzie następujące wiersze danych wyjściowych oznaczone etykietą "TRZY" reprezentują możliwość wykonania niezależnej pracy
THREE: Back in AccessTheWebAsync.
Task getStringTask is started.
About to await getStringTask & return a Task<int> to startButton_Click.
Poniższa instrukcja zawiesza postęp w AccessTheWebAsync, gdy oczekiwany jest getStringTask.
Dim urlContents As String = Await getStringTask
Na poniższym obrazie pokazano przepływ sterowania z client.GetStringAsync do przypisania do getStringTask i od utworzenia getStringTask do zastosowania operatora Await.
Wyrażenie await zawiesza AccessTheWebAsync aż client.GetStringAsync zwróci wartość. W międzyczasie kontrola powraca do obiektu wywołującego AccessTheWebAsync, startButton_Click.
Uwaga / Notatka
Zazwyczaj natychmiast oczekujesz wywołania metody asynchronicznej. Na przykład następujące przypisanie może zastąpić poprzedni kod, który tworzy, a następnie oczekuje na getStringTask: Dim urlContents As String = Await client.GetStringAsync("https://learn.microsoft.com")
W tym temacie operator await zostanie zastosowany później w celu uwzględnienia wierszy wyjściowych, które oznaczają przepływ sterowania za pośrednictwem programu.
Krok CZWARTY
Zadeklarowany zwracany typ to AccessTheWebAsyncTask(Of Integer). W związku z tym, gdy AccessTheWebAsync jest zawieszony, zwraca zadanie liczby całkowitej do startButton_Click. Należy pamiętać, że zwrócone zadanie nie jest getStringTask. Zwrócone zadanie jest nowym zadaniem typu całkowitego, które reprezentuje to, co należy wykonać w zawieszonej metodzie AccessTheWebAsync. Zadanie to obietnica od AccessTheWebAsync na zwrócenie liczby całkowitej, kiedy zadanie zostanie ukończone.
Poniższa instrukcja przypisuje to zadanie do zmiennej getLengthTask .
Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
Podobnie jak w przypadku AccessTheWebAsync, startButton_Click może kontynuować pracę, która nie zależy od wyników zadania asynchronicznego (getLengthTask), dopóki zadanie nie zostanie oczekiwane. Następujące wiersze wyjściowe reprezentują pracę:
FOUR: Back in startButton_Click.
Task getLengthTask is started.
About to await getLengthTask -- no caller to return to.
Postęp w startButton_Click jest zawieszony, gdy oczekiwany jest getLengthTask. Następująca instrukcja przypisania zawiesza startButton_Click aż AccessTheWebAsync będzie ukończone.
Dim contentLength As Integer = Await getLengthTask
Na poniższej ilustracji strzałki pokazują przepływ sterowania od wyrażenia await w AccessTheWebAsync do przypisania wartości w getLengthTask, a następnie normalne przetwarzanie w startButton_Click aż do momentu oczekiwania na getLengthTask.
Krok PIĘĆ
Gdy client.GetStringAsync sygnalizuje, że jest ukończone, przetwarzanie w AccessTheWebAsync jest zwalniane z zawieszenia i może kontynuować po instrukcji await. Następujące wiersze danych wyjściowych reprezentują wznowienie przetwarzania:
FIVE: Back in AccessTheWebAsync.
Task getStringTask is complete.
Processing the return statement.
Exiting from AccessTheWebAsync.
Operand instrukcji return urlContents.Length jest przechowywany w zadaniu, które zwraca AccessTheWebAsync. Wyrażenie await pobiera wartość z getLengthTask w startButton_Click.
Na poniższym obrazku przedstawiono przekazanie kontroli po zakończeniu client.GetStringAsync (i getStringTask).
AccessTheWebAsync działa do ukończenia, a kontrola powraca do startButton_Click, który oczekuje na ukończenie.
Krok SZEŚĆ
Gdy AccessTheWebAsync sygnalizuje ukończenie, przetwarzanie może kontynuować po instrukcji await w startButton_Async. W rzeczywistości program nie ma nic więcej do zrobienia.
Następujące wiersze danych wyjściowych reprezentują wznowienie przetwarzania w pliku startButton_Async:
SIX: Back in startButton_Click.
Task getLengthTask is finished.
Result from AccessTheWebAsync is stored in contentLength.
About to display contentLength and exit.
Wyrażenie await pobiera z getLengthTask wartości całkowitej, która jest operandem instrukcji return w pliku AccessTheWebAsync. Poniższa instrukcja przypisuje tej wartości do zmiennej contentLength .
Dim contentLength As Integer = Await getLengthTask
Na poniższej ilustracji przedstawiono powrót kontrolki z AccessTheWebAsync do startButton_Click.