Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
С помощью ключевых слов Async и Await можно легче создавать и поддерживать асинхронные программы. Однако результаты могут удивить вас, если вы не понимаете, как работает ваша программа. В этом разделе отслеживается поток управления с помощью простой асинхронной программы, чтобы показать, когда элемент управления перемещается из одного метода в другой и какие сведения передаются каждый раз.
Замечание
Ключевые слова Async и Await были введены в Visual Studio 2012.
Как правило, вы помечаете методы, содержащие асинхронный код с помощью модификатора Async . В методе, помеченном асинхронным модификатором, можно использовать оператор Await (Visual Basic), чтобы указать, где метод приостанавливает ожидание завершения вызываемого асинхронного процесса. Дополнительные сведения см. в статье асинхронное программирование с помощью Async и Await (Visual Basic).
В следующем примере используются асинхронные методы для скачивания содержимого указанного веб-сайта в виде строки и отображения длины строки. Пример содержит следующие два метода.
startButton_Click, который вызываетAccessTheWebAsyncи отображает результат.AccessTheWebAsync, который скачивает содержимое веб-сайта в виде строки и возвращает длину строки.AccessTheWebAsyncиспользует асинхронный HttpClient метод, GetStringAsync(String)чтобы скачать содержимое.
Нумерованные линии отображения отображаются в стратегических точках по всей программе, чтобы понять, как выполняется программа, и объяснить, что происходит в каждой точке, помеченной. Отображаемые строки обозначены как "ONE" по "ШЕСТЬ". Метки представляют порядок, в котором программа достигает этих строк кода.
В следующем коде показана структура программы.
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
В каждом из помеченных мест с надписями "ONE" до "SIX" отображается информация о текущем состоянии программы. Выводятся следующие выходные данные:
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.
Настройка программы
Вы можете скачать код, который этот раздел использует из MSDN, или создать его самостоятельно.
Замечание
Чтобы запустить пример, необходимо установить Visual Studio 2012 или более поздней версии и .NET Framework 4.5 или более поздней версии на компьютере.
Скачивание программы
Вы можете скачать приложение по этой теме из примера Async: управление потоком в асинхронных программах. Эти шаги открывают и запускают программу.
Распакуйте скачанный файл и запустите Visual Studio.
В строке меню выберите "Файл", "Открыть", "Проект или решение".
Перейдите в папку с распакованным примером кода, откройте файл решения (.sln), а затем выберите ключ F5 для сборки и запуска проекта.
Создание программы самостоятельно
Следующий проект Windows Presentation Foundation (WPF) содержит пример кода для этого раздела.
Чтобы запустить проект, выполните следующие действия.
Запустите Visual Studio.
В строке меню выберите "Файл", "Создать", "Проект".
Откроется диалоговое окно "Новый проект ".
В области установленных шаблонов выберите Visual Basic и выберите приложение WPF из списка типов проектов.
Введите
AsyncTracerимя проекта и нажмите кнопку "ОК ".Новый проект появится в обозревателе решений.
В редакторе Visual Studio Code выберите вкладку MainWindow.xaml .
Если вкладка не отображается, откройте контекстное меню mainWindow.xaml в обозревателе решений и выберите команду View Code.
В представлении XAML MainWindow.xaml замените код следующим кодом.
<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>Простое окно, содержащее текстовое поле и кнопку, отображается в представлении дизайна MainWindow.xaml.
Добавьте ссылку для System.Net.Http.
В обозревателе решений откройте контекстное меню для MainWindow.xaml.vb и выберите команду "Просмотреть код".
В MainWindow.xaml.vb замените код следующим кодом.
' 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Нажмите клавишу F5, чтобы запустить программу, а затем нажмите кнопку Start .
Должны появиться следующие выходные данные:
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.
Трассировка программы
Шаги ОДИН и ДВА
Первые две строки экрана трассируют путь, где startButton_Click вызывает AccessTheWebAsync, а AccessTheWebAsync вызывает асинхронный метод HttpClientGetStringAsync(String). На следующем рисунке показаны переходы от одного метода к другому.
Возвращаемый тип AccessTheWebAsync и client.GetStringAsync — Task<TResult>. Для AccessTheWebAsync, TResult является целым числом. Для GetStringAsync, TResult является строкой. Дополнительные сведения о типах возврата асинхронного метода см. в статье Async Return Types (Visual Basic).
Асинхронный метод, возвращающий задачу, возвращает экземпляр задачи, когда управление возвращается вызывающему объекту. Управление возвращается из асинхронного метода к вызывающей стороне либо при обнаружении оператора Await в вызываемом методе, либо при завершении вызываемого метода. Отображаемые строки, помеченные как "ТРИ" и "ШЕСТЬ", трассируют эту часть процесса.
Шаг ТРИ
В AccessTheWebAsync вызывается асинхронный метод GetStringAsync(String) для загрузки содержимого целевой веб-страницы. Управление возвращается от client.GetStringAsync к AccessTheWebAsync, когда происходит возврат из client.GetStringAsync.
Метод client.GetStringAsync возвращает задачу типа string, которая назначена переменной getStringTask в AccessTheWebAsync. В следующей строке в примере программы показан вызов client.GetStringAsync и назначение.
Dim getStringTask As Task(Of String) = client.GetStringAsync("https://learn.microsoft.com")
Вы можете рассматривать задачу как обещание со стороны client.GetStringAsync в конце концов создать фактическую строку. В то же время, если у AccessTheWebAsync есть работа, которая не зависит от обещанной строки от client.GetStringAsync, эта работа может продолжаться, пока client.GetStringAsync ожидает. В примере строки выходных данных, обозначенные как "ТРИ", представляют собой возможность для выполнения самостоятельной работы.
THREE: Back in AccessTheWebAsync.
Task getStringTask is started.
About to await getStringTask & return a Task<int> to startButton_Click.
Следующее утверждение приостанавливает прогресс в AccessTheWebAsync, когда getStringTask ожидается.
Dim urlContents As String = Await getStringTask
На следующем рисунке показан поток управления от client.GetStringAsync до присваивания getStringTask, а затем от создания getStringTask до применения оператора Await.
Выражение await приостанавливается AccessTheWebAsync до тех пор, пока client.GetStringAsync не возвращает. В то же время контроль возвращается вызывающему объекту AccessTheWebAsync, startButton_Click.
Замечание
Обычно после вызова асинхронного метода ожидание начинается сразу. Например, следующее назначение может заменить предыдущий код, который создает, а затем ожидает getStringTask: Dim urlContents As String = Await client.GetStringAsync("https://learn.microsoft.com")
В этом разделе оператор await применяется позже, чтобы учитывать выходные строки, которые обозначают поток управления через программу.
Шаг ЧЕТЫРЕ
Объявленный тип возвращаемого значения AccessTheWebAsync — Task(Of Integer). Поэтому, когда AccessTheWebAsync приостанавливается, она возвращает задачу, которая выдает целочисленное значение startButton_Click. Вы должны понимать, что возвращаемая задача не getStringTask. Возвращаемая задача — это новая задача целого числа, представляющая то, что осталось сделать в приостановленном методе AccessTheWebAsync. Задача — это обещание от AccessTheWebAsync создать целое число, когда задача будет завершена.
Следующая инструкция назначает эту задачу переменной getLengthTask .
Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
Как и в случае AccessTheWebAsync, startButton_Click можно продолжать работу, которая не зависит от результатов асинхронной задачи (getLengthTask) до ожидания задачи. Следующие выходные строки представляют собой следующую работу:
FOUR: Back in startButton_Click.
Task getLengthTask is started.
About to await getLengthTask -- no caller to return to.
Продвижение startButton_Click приостанавливается при ожидании getLengthTask. Следующий оператор присваивания приостанавливает действие startButton_Click до завершения AccessTheWebAsync.
Dim contentLength As Integer = Await getLengthTask
На следующем рисунке стрелки показывают поток управления от выражения await в AccessTheWebAsync к назначению значения getLengthTask, а затем обычная обработка в startButton_Click продолжается, пока getLengthTask не будет ожидаемым.
Шаг ПЯТЬ
Когда client.GetStringAsync сигнализирует о завершении, обработка AccessTheWebAsync освобождается от приостановки и может продолжаться после инструкции await. Следующие строки выходных данных представляют возобновление обработки:
FIVE: Back in AccessTheWebAsync.
Task getStringTask is complete.
Processing the return statement.
Exiting from AccessTheWebAsync.
Операнд инструкции return urlContents.Length хранится в задаче, которую возвращает AccessTheWebAsync. Выражение await извлекает это значение из getLengthTask в startButton_Click.
На следующем рисунке показана передача управления после завершения client.GetStringAsync и getStringTask.
AccessTheWebAsync выполняется до полного завершения, и элемент управления переходит к startButton_Click, который находится в ожидании завершения.
Шаг ШЕСТЬ
Когда AccessTheWebAsync сигнализирует о завершении, обработка может продолжиться после инструкции await в startButton_Async. На самом деле, программе больше ничего не нужно делать.
Следующие строки выходных данных представляют возобновление обработки в startButton_Async:
SIX: Back in startButton_Click.
Task getLengthTask is finished.
Result from AccessTheWebAsync is stored in contentLength.
About to display contentLength and exit.
Выражение await извлекает целочисленное значение из getLengthTask, которое является операндом инструкции return в AccessTheWebAsync. Следующая инструкция назначает это значение переменной contentLength .
Dim contentLength As Integer = Await getLengthTask
На изображении ниже показана передача контроля от AccessTheWebAsync к startButton_Click.
См. также
- Асинхронное программирование с использованием ключевых слов Async и Await (Visual Basic)
- Async Return Types (Visual Basic) (Типы возвращаемых значений Async (Visual Basic))
- Пошаговое руководство. Доступ к Интернету с помощью Async и Await (Visual Basic)
- Пример async: поток управления в асинхронных программах (C# и Visual Basic)