Tipos de retorno assíncronos (Visual Basic)
Métodos assíncronos têm três possíveis tipos de retorno: Task<TResult>, Task e void. No Visual Basic, o tipo de retorno void é gravado como um procedimento Sub. Para obter mais informações sobre os métodos assíncronos, consulte Programação assíncrona com Async e Await (Visual Basic).
Cada tipo de retorno é examinado em uma das seções a seguir e você pode encontrar um exemplo completo que usa todos os três tipos no final do tópico.
Observação
Para executar o exemplo, você deve ter o Visual Studio 2012 ou mais recente e o .NET Framework 4.5 ou posterior instalados no seu computador.
Tipo de retorno Task(T)
O tipo de retorno Task<TResult> é usado para um método assíncrono que contém uma instrução Return na qual o operando tem o tipo TResult
.
No exemplo a seguir, o método assíncrono TaskOfT_MethodAsync
contém uma instrução return que retorna um número inteiro. Portanto, a declaração do método deve especificar um tipo de retorno de Task(Of Integer)
.
' TASK(OF T) EXAMPLE
Async Function TaskOfT_MethodAsync() As Task(Of Integer)
' The body of an async method is expected to contain an awaited
' asynchronous call.
' Task.FromResult is a placeholder for actual work that returns a string.
Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString())
' The method then can process the result in some way.
Dim leisureHours As Integer
If today.First() = "S" Then
leisureHours = 16
Else
leisureHours = 5
End If
' Because the return statement specifies an operand of type Integer, the
' method must have a return type of Task(Of Integer).
Return leisureHours
End Function
Quando TaskOfT_MethodAsync
é chamado de dentro de uma expressão await, a expressão await recupera o valor inteiro (o valor de leisureHours
) que está armazenado na tarefa que é retornada pelo TaskOfT_MethodAsync
. Para obter mais informações sobre expressões await, consulte Operador await.
O código a seguir chama e aguarda o método TaskOfT_MethodAsync
. O resultado é atribuído à variável result1
.
' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()
Você pode entender melhor como isso acontece, separando a chamada ao TaskOfT_MethodAsync
da aplicação do Await
, como mostrado no código a seguir. Uma chamada ao método TaskOfT_MethodAsync
que não é aguardada imediatamente, retorna um Task(Of Integer)
, como você esperaria da declaração do método. A tarefa é atribuída à variável integerTask
no exemplo. Já que integerTask
é um Task<TResult>, ele contém uma propriedade Result do tipo TResult
. Nesse caso, TResult representa um tipo inteiro. Quando Await
é aplicado à integerTask
, a expressão await é avaliada como o conteúdo da propriedade Result de integerTask
. O valor é atribuído à variável result2
.
Aviso
A propriedade Result é uma propriedade de bloqueio. Se você tentar acessá-la antes que sua tarefa seja concluída, o thread que está ativo no momento será bloqueado até que a tarefa seja concluída e o valor esteja disponível. Na maioria dos casos, você deve acessar o valor usando Await
em vez de acessar a propriedade diretamente.
' Call and await in separate statements.
Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync()
' You can do other work that does not rely on resultTask before awaiting.
textBox1.Text &= "Application can continue working while the Task(Of T) runs. . . . " & vbCrLf
Dim result2 As Integer = Await integerTask
As instruções de exibição no código a seguir verificam se os valores da variável result1
, da variável result2
e da propriedade Result
são os mesmos. Lembre-se que a propriedade Result
é uma propriedade de bloqueio e não deve ser acessada antes que sua tarefa tenha sido aguardada.
' Display the values of the result1 variable, the result2 variable, and
' the resultTask.Result property.
textBox1.Text &= vbCrLf & $"Value of result1 variable: {result1}" & vbCrLf
textBox1.Text &= $"Value of result2 variable: {result2}" & vbCrLf
textBox1.Text &= $"Value of resultTask.Result: {integerTask.Result}" & vbCrLf
Tipo de retorno Task
Os métodos assíncronos que não contêm uma instrução return ou que contêm uma instrução return que não retorna um operando, normalmente têm um tipo de retorno de Task. Esses métodos seriam procedimentos Sub se eles fossem escritos para serem executados de forma síncrona. Se você usar um tipo de retorno Task
para um método assíncrono, um método de chamada poderá usar um operador Await
para suspender a conclusão do chamador até que o método assíncrono chamado seja concluído.
No exemplo a seguir, o método assíncrono Task_MethodAsync
não contém uma instrução return. Portanto, você especifica um tipo de retorno de Task
para o método, que permite que Task_MethodAsync
seja aguardado. A definição do tipo Task
não inclui uma propriedade Result
para armazenar um valor retornado.
' TASK EXAMPLE
Async Function Task_MethodAsync() As Task
' The body of an async method is expected to contain an awaited
' asynchronous call.
' Task.Delay is a placeholder for actual work.
Await Task.Delay(2000)
textBox1.Text &= vbCrLf & "Sorry for the delay. . . ." & vbCrLf
' This method has no return statement, so its return type is Task.
End Function
O Task_MethodAsync
é chamado e aguardado, usando uma instrução await, em vez de uma expressão await, semelhante à instrução de chamada a um método síncrono Sub
ou de retorno void. A aplicação de um operador Await
, nesse caso, não produz um valor.
O código a seguir chama e aguarda o método Task_MethodAsync
.
' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
Como no exemplo Task<TResult> anterior, você pode separar a chamada ao Task_MethodAsync
da aplicação de um operador Await
, como mostrado no código a seguir. No entanto, lembre-se que uma Task
não tem uma propriedade Result
e que nenhum valor será produzido quando um operador await for aplicado a uma Task
.
O código a seguir separa a chamada ao Task_MethodAsync
da espera pela tarefa que Task_MethodAsync
retorna.
' Call and await in separate statements.
Dim simpleTask As Task = Task_MethodAsync()
' You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text &= vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf
Await simpleTask
Tipo de retorno void
O uso primário de procedimentos Sub
está nos manipuladores de eventos, nos quais não há nenhum tipo de retorno (conhecido como um tipo de retorno void em outras linguagens). Um retorno void também pode ser usado para substituir métodos que retornem void ou para métodos que executem atividades que podem ser categorizadas como "disparar e esquecer". No entanto, você deve retornar um Task
sempre que possível, porque um método assíncrono que retorna void não pode ser aguardado. Qualquer chamador desse método deve ser capaz de continuar até a conclusão, sem aguardar a conclusão do método assíncrono chamado e o chamador deve ser independente de todos os valores ou exceções gerados pelo método assíncrono.
O chamador de um método assíncrono de retorno void não pode capturar exceções que são lançadas pelo método e essas exceções sem tratamento provavelmente causarão falha do seu aplicativo. Se ocorrer uma exceção em um método assíncrono que retorna uma Task ou uma Task<TResult>, a exceção será armazenada na tarefa retornada e relançada quando a tarefa for aguardada. Portanto, verifique se qualquer método assíncrono que pode produzir uma exceção tem um tipo de retorno de Task ou Task<TResult> e que as chamadas ao método são aguardadas.
Para obter mais informações sobre como capturar exceções nos métodos assíncronos, consulte a Instrução Try... Catch... Finally.
O código a seguir define um manipulador de eventos assíncrono.
' SUB EXAMPLE
Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click
textBox1.Clear()
' Start the process and await its completion. DriverAsync is a
' Task-returning async method.
Await DriverAsync()
' Say goodbye.
textBox1.Text &= vbCrLf & "All done, exiting button-click event handler."
End Sub
Exemplo completo
O projeto WPF (Windows Presentation Foundation) a seguir contém os exemplos de código deste tópico.
Para executar o projeto, realize as seguintes etapas:
Inicie o Visual Studio.
Na barra de menus, escolha Arquivo, Novo, Projeto.
A caixa de diálogo Novo Projeto será aberta.
Em Instalado, categoria Modelos, escolha Visual Basic e, em seguida, escolha Windows. Escolha Aplicativo WPF na lista de tipos de projeto.
Digite
AsyncReturnTypes
como o nome do projeto e, em seguida, escolha o botão OK.O novo projeto aparece no Gerenciador de Soluções.
No Editor do Visual Studio Code, 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, em seguida, escolha Abrir.
Na janela XAML de MainWindow.xaml, substitua o código pelo código a seguir.
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Button x:Name="button1" Content="Start" HorizontalAlignment="Left" Margin="214,28,0,0" VerticalAlignment="Top" Width="75" HorizontalContentAlignment="Center" FontWeight="Bold" FontFamily="Aharoni" Click="button1_Click"/> <TextBox x:Name="textBox1" Margin="0,80,0,0" TextWrapping="Wrap" FontFamily="Lucida Console"/> </Grid> </Window>
Uma janela simples, contendo uma caixa de texto e um botão, aparecerá na janela Design de MainWindow.xaml.
No Gerenciador de Soluções, abra o menu de atalho para MainWindow.xaml.vb e, em seguida, escolha Exibir Código.
Substitua o código em MainWindow.xaml.vb pelo código a seguir.
Class MainWindow ' SUB EXAMPLE Async Sub button1_Click(sender As Object, e As RoutedEventArgs) Handles button1.Click textBox1.Clear() ' Start the process and await its completion. DriverAsync is a ' Task-returning async method. Await DriverAsync() ' Say goodbye. textBox1.Text &= vbCrLf & "All done, exiting button-click event handler." End Sub Async Function DriverAsync() As Task ' Task(Of T) ' Call and await the Task(Of T)-returning async method in the same statement. Dim result1 As Integer = Await TaskOfT_MethodAsync() ' Call and await in separate statements. Dim integerTask As Task(Of Integer) = TaskOfT_MethodAsync() ' You can do other work that does not rely on resultTask before awaiting. textBox1.Text &= "Application can continue working while the Task(Of T) runs. . . . " & vbCrLf Dim result2 As Integer = Await integerTask ' Display the values of the result1 variable, the result2 variable, and ' the resultTask.Result property. textBox1.Text &= vbCrLf & $"Value of result1 variable: {result1}" & vbCrLf textBox1.Text &= $"Value of result2 variable: {result2}" & vbCrLf textBox1.Text &= $"Value of resultTask.Result: {integerTask.Result}" & vbCrLf ' Task ' Call and await the Task-returning async method in the same statement. Await Task_MethodAsync() ' Call and await in separate statements. Dim simpleTask As Task = Task_MethodAsync() ' You can do other work that does not rely on simpleTask before awaiting. textBox1.Text &= vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf Await simpleTask End Function ' TASK(OF T) EXAMPLE Async Function TaskOfT_MethodAsync() As Task(Of Integer) ' The body of an async method is expected to contain an awaited ' asynchronous call. ' Task.FromResult is a placeholder for actual work that returns a string. Dim today As String = Await Task.FromResult(Of String)(DateTime.Now.DayOfWeek.ToString()) ' The method then can process the result in some way. Dim leisureHours As Integer If today.First() = "S" Then leisureHours = 16 Else leisureHours = 5 End If ' Because the return statement specifies an operand of type Integer, the ' method must have a return type of Task(Of Integer). Return leisureHours End Function ' TASK EXAMPLE Async Function Task_MethodAsync() As Task ' The body of an async method is expected to contain an awaited ' asynchronous call. ' Task.Delay is a placeholder for actual work. Await Task.Delay(2000) textBox1.Text &= vbCrLf & "Sorry for the delay. . . ." & vbCrLf ' This method has no return statement, so its return type is Task. End Function End Class
Escolha a tecla F5 para executar o programa e, em seguida, o botão Iniciar.
A saída a seguir deverá aparecer:
Application can continue working while the Task<T> runs. . . . Value of result1 variable: 5 Value of result2 variable: 5 Value of integerTask.Result: 5 Sorry for the delay. . . . Application can continue working while the Task runs. . . . Sorry for the delay. . . . All done, exiting button-click event handler.
Confira também
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de