Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Você pode escrever e manter programas assíncronos mais facilmente usando as Async
palavras-chave e Await
. No entanto, os resultados podem surpreendê-lo se você não entender como seu programa funciona. Este tópico rastreia o fluxo de controle por meio de um programa assíncrono simples para mostrar quando o controle se move de um método para outro e quais informações são transferidas a cada vez.
Observação
As Async
palavras-chave e Await
foram introduzidas no Visual Studio 2012.
Em geral, você marca métodos que contêm código assíncrono com o modificador Assíncrono . Em um método marcado com um modificador assíncrono, você pode usar um operador Await (Visual Basic) para especificar onde o método pausa para aguardar a conclusão de um processo assíncrono chamado. Para obter mais informações, consulte Programação assíncrona com Async e Await (Visual Basic).
O exemplo a seguir usa métodos async para baixar o conteúdo de um site especificado como uma cadeia de caracteres e para exibir o comprimento da cadeia de caracteres. O exemplo contém os dois métodos a seguir.
startButton_Click
, que chamaAccessTheWebAsync
e exibe o resultado.AccessTheWebAsync
, que baixa o conteúdo de um site como uma cadeia de caracteres e retorna o comprimento da cadeia de caracteres.AccessTheWebAsync
usa um método assíncrono HttpClient , GetStringAsync(String), para baixar o conteúdo.
Linhas de exibição numeradas aparecem em pontos estratégicos ao longo do programa para ajudá-lo a entender como o programa é executado e explicar o que acontece em cada ponto marcado. As linhas de exibição são rotuladas de "UM" a "SEIS". Os rótulos representam a ordem em que o programa atinge essas linhas de código.
O código a seguir mostra um esboço do programa.
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
Cada um dos locais rotulados, "UM" a "SEIS", exibe informações sobre o estado atual do programa. A seguinte saída é produzida:
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.
Configurar o programa
Você pode baixar o código que este tópico usa do MSDN ou criá-lo você mesmo.
Observação
Para executar o exemplo, você deve ter o Visual Studio 2012 ou mais recente e o .NET Framework 4.5 ou mais recente instalado no seu computador.
Faça o download do programa
Você pode baixar o aplicativo para este tópico em Async Sample: Control Flow in Async Programs. Os passos seguintes abrem e executam o programa.
Descompacte o arquivo baixado e inicie o Visual Studio.
Na barra de menus, escolha Arquivo, Abrir, Projeto/Solução.
Navegue até a pasta que contém o código de exemplo descompactado, abra o arquivo de solução (.sln) e escolha a tecla F5 para criar e executar o projeto.
Construa o programa você mesmo
O seguinte projeto do Windows Presentation Foundation (WPF) contém o exemplo de código para este tópico.
Para executar o projeto, execute as seguintes etapas:
Inicie o Visual Studio.
Na barra de menus, escolha Arquivo, Novo, Projeto.
A caixa de diálogo Novo projeto é aberta.
No painel Modelos Instalados , escolha Visual Basic e, em seguida, escolha Aplicativo WPF na lista de tipos de projeto.
Digite
AsyncTracer
como o nome do projeto e, em seguida, escolha o botão OK .O novo projeto aparece no Gerenciador de Soluções.
No Editor de Códigos do Visual Studio, escolha a guia MainWindow.xaml .
Se a guia não estiver visível, abra o menu de atalho para MainWindow.xaml no Gerenciador de Soluções e escolha View Code.
No modo de exibição XAML de MainWindow.xaml, substitua o código pelo código a seguir.
<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>
Uma janela simples que contém uma caixa de texto e um botão aparece no modo Design de MainWindow.xaml.
Adicione uma referência para System.Net.Http.
No Gerenciador de Soluções, abra o menu de atalho para MainWindow.xaml.vb e escolha Exibir Código.
No MainWindow.xaml.vb , substitua o código pelo código a seguir.
' 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
Escolha a tecla F5 para executar o programa e, em seguida, escolha o botão Iniciar .
A seguinte saída deve aparecer:
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.
Rastrear o programa
Passos UM e DOIS
As duas primeiras linhas de exibição traçam o caminho como startButton_Click
chama AccessTheWebAsync
, e AccessTheWebAsync
chama o método assíncrono HttpClientGetStringAsync(String). A imagem seguinte ilustra as chamadas de um método para outro método.
O tipo de retorno de ambos AccessTheWebAsync
e client.GetStringAsync
é Task<TResult>. Para AccessTheWebAsync
, TResult é um inteiro. Para GetStringAsync
, TResult é uma string. Para obter mais informações sobre tipos de retorno de método assíncrono, consulte Tipos de retorno assíncronos (Visual Basic).
Um método assíncrono de retorno de tarefa retorna uma instância de tarefa quando o controle volta para o chamador. O controle retorna de um método assíncrono para o seu chamador, quando o operador Await
é encontrado no método chamado, ou quando o método chamado termina. As linhas de exibição rotuladas de "TRÊS" a "SEIS" rastreiam essa parte do processo.
Passo TRÊS
No AccessTheWebAsync
, o método GetStringAsync(String) assíncrono é chamado para baixar o conteúdo da página da Web de destino. O controle retorna de client.GetStringAsync
para AccessTheWebAsync
quando client.GetStringAsync
retorna.
O client.GetStringAsync
método retorna uma tarefa de cadeia de caracteres atribuída à getStringTask
variável em AccessTheWebAsync
. A linha a seguir no programa de exemplo mostra a chamada para client.GetStringAsync
e a atribuição.
Dim getStringTask As Task(Of String) = client.GetStringAsync("https://learn.microsoft.com")
Você pode pensar na tarefa como uma promessa feita por client.GetStringAsync
de eventualmente produzir uma cadeia de caracteres real. Enquanto isso, se AccessTheWebAsync
tiver trabalho para fazer que não dependa da string prometida da client.GetStringAsync
, esse trabalho pode continuar enquanto client.GetStringAsync
espera. No exemplo, as seguintes linhas de saída, que são rotuladas como "TRÊS", representam a oportunidade de fazer trabalho independente
THREE: Back in AccessTheWebAsync.
Task getStringTask is started.
About to await getStringTask & return a Task<int> to startButton_Click.
O avanço em AccessTheWebAsync
é suspenso enquanto se aguarda getStringTask
.
Dim urlContents As String = Await getStringTask
A imagem a seguir mostra o fluxo de controle de client.GetStringAsync
para a atribuição em getStringTask
e desde a criação de getStringTask
até à aplicação de um operador Await.
A expressão await suspende AccessTheWebAsync
até que client.GetStringAsync
retorne. Entretanto, o controle é devolvido ao chamador de AccessTheWebAsync
, startButton_Click
.
Observação
Normalmente, você aguarda a chamada para um método assíncrono imediatamente. Por exemplo, a seguinte atribuição pode substituir o código anterior que cria e, em seguida, aguarda getStringTask
: Dim urlContents As String = Await client.GetStringAsync("https://learn.microsoft.com")
Neste tópico, o operador await é aplicado posteriormente para acomodar as linhas de saída que marcam o fluxo de controle através do programa.
Passo QUATRO
O tipo de retorno declarado de AccessTheWebAsync
é Task(Of Integer)
. Portanto, quando o elemento AccessTheWebAsync
é suspenso, retorna uma tarefa de número inteiro para startButton_Click
. Você deve entender que a tarefa retornada não está getStringTask
. A tarefa retornada é uma nova tarefa que envolve um valor inteiro, representando o que ainda falta fazer no método suspenso, AccessTheWebAsync
. A tarefa é uma promessa de AccessTheWebAsync
para produzir um número inteiro quando for concluída.
A instrução a seguir atribui essa tarefa à getLengthTask
variável.
Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
Como no AccessTheWebAsync
, startButton_Click
pode continuar com o trabalho que não depende dos resultados da tarefa assíncrona (getLengthTask
) até que a tarefa seja aguardada. As seguintes linhas de saída representam esse trabalho:
FOUR: Back in startButton_Click.
Task getLengthTask is started.
About to await getLengthTask -- no caller to return to.
O progresso em startButton_Click
é suspenso quando getLengthTask
é aguardado. A seguinte instrução de atribuição suspende startButton_Click
até AccessTheWebAsync
estar concluída.
Dim contentLength As Integer = Await getLengthTask
Na ilustração a seguir, as setas mostram o fluxo de controle da expressão await em AccessTheWebAsync
para a atribuição de um valor para getLengthTask
, seguido pelo processamento normal em startButton_Click
até que getLengthTask
seja aguardado.
Passo CINCO
Quando client.GetStringAsync
sinaliza que está concluído, o processamento em AccessTheWebAsync
é retomado da suspensão e pode continuar após a instrução await. As seguintes linhas de saída representam a retomada do processamento:
FIVE: Back in AccessTheWebAsync.
Task getStringTask is complete.
Processing the return statement.
Exiting from AccessTheWebAsync.
O operando da instrução return, urlContents.Length
, é armazenado na tarefa que AccessTheWebAsync
retorna. A expressão await recupera esse valor de getLengthTask
em startButton_Click
.
A imagem a seguir mostra a transferência de controle após client.GetStringAsync
(e getStringTask
) serem concluídas.
AccessTheWebAsync
é executado até a conclusão, e o controle retorna para startButton_Click
, que está aguardando a conclusão.
Passo SEIS
Quando AccessTheWebAsync
sinaliza que está concluído, o processamento pode continuar após a instrução await em startButton_Async
. Na verdade, o programa não tem mais nada a fazer.
As seguintes linhas de saída representam a retomada do processamento em startButton_Async
:
SIX: Back in startButton_Click.
Task getLengthTask is finished.
Result from AccessTheWebAsync is stored in contentLength.
About to display contentLength and exit.
A expressão await obtém do getLengthTask
o valor inteiro que é o operando da instrução return em AccessTheWebAsync
. A instrução a seguir atribui esse valor à contentLength
variável.
Dim contentLength As Integer = Await getLengthTask
A imagem a seguir mostra o retorno do controle de AccessTheWebAsync
para startButton_Click
.