Share via


Tipos de retorno assíncronos (Visual Basic)

Os métodos assíncronos têm três tipos de retorno possíveis: Task<TResult>, Taske void. No Visual Basic, o tipo de retorno void é escrito como um procedimento Sub . Para obter mais informações sobre 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.

Nota

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.

Tipo de retorno Task(T)

O Task<TResult> tipo de retorno é usado para um método assíncrono que contém uma instrução Return na qual o operando tem tipo TResult.

No exemplo a seguir, o TaskOfT_MethodAsync método async contém uma instrução return que retorna um inteiro. Portanto, a declaração de 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 é chamada de dentro de uma expressão await, a expressão await recupera o valor inteiro (o valor de ) armazenado na tarefa retornada leisureHourspelo TaskOfT_MethodAsync. Para obter mais informações sobre expressões await, consulte Await Operator.

O código a seguir chama e aguarda o método TaskOfT_MethodAsync. O resultado é atribuído à result1 variável.

' 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 para TaskOfT_MethodAsync do aplicativo do Await, como mostra o código a seguir. Uma chamada para o método TaskOfT_MethodAsync que não é imediatamente aguardada retorna um Task(Of Integer), como você esperaria da declaração do método. A tarefa é atribuída à integerTask variável no exemplo. Porque integerTask é um Task<TResult>, ele contém uma Result propriedade do tipo TResult. Neste caso, TResult representa um tipo inteiro. Quando Await é aplicada ao integerTask, a expressão await é avaliada para o conteúdo da Result propriedade de integerTask. O valor é atribuído à result2 variável.

Aviso

A Result propriedade é uma propriedade de bloqueio. Se você tentar acessá-lo 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 display no código a seguir verificam se os valores da result1 variável, da result2 variável e da Result propriedade são os mesmos. Lembre-se de que a Result propriedade é uma propriedade de bloqueio e não deve ser acessada antes que sua tarefa seja 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 de Tarefa

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 geralmente têm um tipo de retorno de Task. Tais métodos seriam procedimentos Sub se fossem escritos para serem executados de forma síncrona. Se você usar um Task tipo de retorno para um método assíncrono, um método de chamada poderá usar um Await operador 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 Task_MethodAsync async não contém uma instrução return. Portanto, você especifica um tipo de retorno de Task para o método, que permite Task_MethodAsync ser aguardado. A definição do tipo não inclui uma Result propriedade para armazenar um valor de Task retorno.

' 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

Task_MethodAsync é chamado e aguardado usando uma instrução await em vez de uma expressão await, semelhante à instrução calling para um método síncrono Sub ou de retorno de vazio. A aplicação de um Await operador, neste 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 anterior Task<TResult> , você pode separar a chamada para Task_MethodAsync do aplicativo de um Await operador, como mostra o código a seguir. No entanto, lembre-se de que um Task não tem uma Result propriedade e que nenhum valor é produzido quando um operador de espera é aplicado a um Task.

O código a seguir separa a chamada Task_MethodAsync da espera da 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 vazio

O principal uso de procedimentos é em manipuladores de eventos, onde não há nenhum tipo de retorno (referido como um tipo de Sub retorno vazio em outros idiomas). Um retorno de vazio também pode ser usado para substituir métodos de retorno de vazio ou para métodos que executam atividades que podem ser categorizadas como "fogo e esquecimento". No entanto, você deve retornar um Task sempre que possível, porque um método assíncrono de retorno de vazio não pode ser aguardado. Qualquer chamador de tal método deve ser capaz de continuar a conclusão sem esperar que o método assíncrono chamado termine, e o chamador deve ser independente de quaisquer valores ou exceções que o método assíncrono gera.

O chamador de um método assíncrono de retorno de vazio não pode capturar exceções que são lançadas do método, e essas exceções não tratadas provavelmente farão com que seu aplicativo falhe. Se ocorrer uma exceção em um método assíncrono que retorna um Task ou Task<TResult>, a exceção será armazenada na tarefa retornada e relançada quando a tarefa for aguardada. Portanto, certifique-se de que qualquer método assíncrono que possa produzir uma exceção tenha um tipo de retorno de Task ou Task<TResult> e que as chamadas para o método sejam aguardadas.

Para obter mais informações sobre como capturar exceções em métodos assíncronos, consulte Tentar... Pegar... Finalmente Declaração.

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 seguinte projeto do Windows Presentation Foundation (WPF) contém os exemplos de código deste tópico.

Para executar o projeto, execute as seguintes etapas:

  1. Inicie o Visual Studio.

  2. Na barra de menus, escolha Arquivo, Novo, Projeto.

    A caixa de diálogo Novo projeto é aberta.

  3. Na categoria Modelos instalados, escolhaVisual Basic e, em seguida, escolha Windows. Escolha Aplicativo WPF na lista de tipos de projeto.

  4. Digite AsyncReturnTypes como o nome do projeto e, em seguida, escolha o botão OK .

    O novo projeto aparece no Gerenciador de Soluções.

  5. 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 Abrir.

  6. 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 que contém uma caixa de texto e um botão aparece na janela Design de MainWindow.xaml.

  7. No Gerenciador de Soluções, abra o menu de atalho para MainWindow.xaml.vb e escolha Exibir Código.

  8. Substitua o código no 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
    
  9. Escolha a tecla F5 para executar o programa e, em seguida, escolha o botão Iniciar .

    A seguinte saída deve 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.
    

Consulte também