Tipos de retorno de Async (C# e Visual Basic)

Os métodos de Async têm três tipos de retorno possíveis: Task<TResult>, Task, e vácuo.Em Visual Basic, o tipo de retorno vago é escrito como um procedimento de Sub .Para obter mais informações sobre métodos de async, consulte Programação com Async assíncrona e esperar (C# e Visual Basic).

Cada tipo de retorno é examinado em uma das seguintes seções, e você pode localizar um exemplo completo que usa todos os três tipos no final do tópico.

ObservaçãoObservação

Para executar o exemplo, você deve ter o Visual Studio 2012 O Visual Studio express library 2012 para a área de trabalho do Windows, ou .NET Framework 4.5 instalado no seu computador.

Este tópico contém as seções a seguir.

  • Tarefa (T) tipo de retorno
  • Encarregue o tipo de retorno
  • Tipo de retorno vago
  • Exemplo Completo
  • Tópicos relacionados

Tarefa (T) tipo de retorno

O tipo de retorno de Task<TResult> é usado para um método de async que contém uma declaração de Retorno (Visual Basic) ou de retorno (C#) em que o operando tem o tipo TResult.

No exemplo, o método de async de TaskOfT_MethodAsync contém uma declaração de retorno que retorna um número inteiro.Como consequência, a declaração de método deve especificar um tipo de retorno de Task(Of Integer) em Visual Basic ou de Task<int> C#.

' 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<T> EXAMPLE
async Task<int> TaskOfT_MethodAsync()
{
    // The body of the method is expected to contain an awaited asynchronous
    // call.
    // Task.FromResult is a placeholder for actual work that returns a string.
    var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());

    // The method then can process the result in some way.
    int leisureHours;
    if (today.First() == 'S')
        leisureHours = 16;
    else
        leisureHours = 5;

    // Because the return statement specifies an operand of type int, the
    // method must have a return type of Task<int>.
    return leisureHours;
}

Quando TaskOfT_MethodAsync é chamado de uma expressão de espera, a expressão de espera retorna o valor inteiro (o valor de leisureHours) que é armazenado na tarefa que é retornada por TaskOfT_MethodAsync.Para obter mais informações sobre expressões de espera, consulte Aguardar o operador (Visual Basic) ou aguardar (referência de C#).

O código a seguir chama o método TaskOfT_MethodAsynce espera.O resultado é atribuído à variável de result1 .

' Call and await the Task(Of T)-returning async method in the same statement.
Dim result1 As Integer = Await TaskOfT_MethodAsync()
// Call and await the Task<T>-returning async method in the same statement.
int result1 = await TaskOfT_MethodAsync();

Você pode entender como isso acontece separando a chamada a TaskOfT_MethodAsync de aplicativo de Await ou de await, porque o código a seguir mostra.Uma chamada para o método TaskOfT_MethodAsync que não é retorna imediatamente esperado um Task(Of Integer) ou Task<int>, como você faria espera da declaração de método.A tarefa é atribuído à variável de integerTask no exemplo.Porque integerTask é Task<TResult>, contém uma propriedade de Result de tipo TResult.Nesse caso, TResult representa um tipo inteiro.Quando Await ou await são aplicados a integerTask, a expressão de espera avalia nos conteúdos de propriedade de Result de integerTask.O valor é atribuído à variável de result2 .

Observação de cuidadoCuidado

A propriedade de Result é uma propriedade de bloqueio.Se você tentar acessar a sua tarefa antes que ela seja concluída, o segmento que está atualmente ativa está bloqueado até termina a tarefa e o valor está disponível.Na maioria dos casos, você deve acessar o valor usando Await ou 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 &= String.Format("Application can continue working while the Task(Of T) runs. . . . " & vbCrLf)

Dim result2 As Integer = Await integerTask
// Call and await in separate statements.
Task<int> integerTask = TaskOfT_MethodAsync();

// You can do other work that does not rely on integerTask before awaiting.
textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n");

int result2 = await integerTask;

As instruções de exibição no código a seguir verifique que os valores da variável de result1 , da variável de result2 , e a propriedade de Result sejam os mesmos.Lembre-se de que a propriedade de Result é uma propriedade de bloqueio e não deve ser acessada antes que a tarefa é esperada.

' Display the values of the result1 variable, the result2 variable, and
' the resultTask.Result property.
textBox1.Text &= String.Format(vbCrLf & "Value of result1 variable:   {0}" & vbCrLf, result1)
textBox1.Text &= String.Format("Value of result2 variable:   {0}" & vbCrLf, result2)
textBox1.Text &= String.Format("Value of resultTask.Result:  {0}" & vbCrLf, integerTask.Result)
// Display the values of the result1 variable, the result2 variable, and
// the integerTask.Result property.
textBox1.Text += String.Format("\r\nValue of result1 variable:   {0}\r\n", result1);
textBox1.Text += String.Format("Value of result2 variable:   {0}\r\n", result2);
textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result);

Encarregue o tipo de retorno

Os métodos de Async que não contém uma declaração return ou que contém uma declaração de retorno que não retorna um operando geralmente têm um tipo de retorno de Task.Esses métodos vago- fossem retornando os métodos (procedimentos deSub no Visual Basic) se foram escritos para executar forma síncrona.Se você usar um tipo de retorno de Task para um método de async, um método de chamada pode usar um operador de espera para suspender a conclusão do chamador até que o método chamado de async terminar.

No exemplo, o método Task_MethodAsync de async não contém uma declaração return.Como consequência, você especifica um tipo de retorno de Task para o método, que permite que Task_MethodAsync a ser esperado.A definição do tipo de Task não incluir uma propriedade de Result para armazenar o valor de 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 &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf)

    ' This method has no return statement, so its return type is Task. 
End Function
// TASK EXAMPLE
async Task Task_MethodAsync()
{
    // 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);
    // Task.Delay delays the following line by two seconds.
    textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");

    // This method has no return statement, so its return type is Task.  
}

Task_MethodAsync é chamado e esperado usando uma instrução de espera em vez de uma expressão de espera, semelhante a instrução de chamada para Sub ou um método síncrono vago- retornar.O aplicativo de um operador de espera nesse caso não produz um valor.

O código a seguir chama o método Task_MethodAsynce espera.

' Call and await the Task-returning async method in the same statement.
Await Task_MethodAsync()
// Call and await the Task-returning async method in the same statement.
await Task_MethodAsync();

Como no exemplo anterior de Task<TResult> , você pode separar a chamada a Task_MethodAsync de aplicativo de um operador de espera, porque o código a seguir mostra.No entanto, lembre-se que Task não tem uma propriedade de Result , e que nenhum valor é gerado quando um operador de espera é aplicado a Task.

O seguinte código que chama Task_MethodAsync de aguardar que a 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 &= String.Format(vbCrLf & "Application can continue working while the Task runs. . . ." & vbCrLf)

Await simpleTask
// Call and await in separate statements.
Task simpleTask = Task_MethodAsync();

// You can do other work that does not rely on simpleTask before awaiting.
textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n");

await simpleTask;

Tipo de retorno vago

O uso primário do tipo de retorno vago (procedimentos deSub no Visual Basic) está nos manipuladores de eventos, onde um tipo de retorno vago é necessário.Um retorno vago também pode ser usado para substituir vago- métodos para retornar ou métodos que executam as atividades que podem ser categorizadas como “fogo - e -” esqueça. No entanto, você deve retornar Task sempre que possível, porque um método vago- retornando de async não pode ser esperado.Qualquer chamador desse método deve poder continuar para a conclusão sem esperar o método chamado de async para concluir, e o chamador deve ser independentes de quaisquer valores ou exceções que o método de async gerar.

O chamador de um método vago- retornando de async não pode capturar exceções que são geradas de método, e essas exceções não tratadas provavelmente fazer com que o aplicativo.Se ocorrer uma exceção em um método de async que retorna Task ou Task<TResult>, a exceção é armazenada na tarefa retornado, e em rethrown quando a tarefa é esperada.Como consequência, certifique-se de que qualquer método de async que podem gerar uma exceção tem um tipo de retorno de Task ou de Task<TResult> e que chamadas para o método são esperados.

Para obter mais informações sobre como capturar exceções em métodos de async, consulte try-catch (referência de C#) ou Try...Catch...Instrução finally (Visual Basic).

O código a seguir define um manipulador de eventos de async.

' 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
// VOID EXAMPLE
private async void button1_Click(object sender, RoutedEventArgs e)
{
    textBox1.Clear();

    // Start the process and await its completion. DriverAsync is a 
    // Task-returning async method.
    await DriverAsync();

    // Say goodbye.
    textBox1.Text += "\r\nAll done, exiting button-click event handler.";
}

Exemplo Completo

O exemplo a seguir projeto Windows Presentation Foundation (WPF) contém exemplos de código deste tópico.

Para executar o projeto, execute as seguintes etapas:

  1. Inicie o Visual Studio.

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

    A Caixa de diálogo Novo Projeto é exibida.

  3. Em Instalado, a categoria de Modelos , escolha Visual Basic ou Visual C#, e clique em Janelas.Escolha Aplicativo WPF da lista de tipos de projeto.

  4. Entre em AsyncReturnTypes como o nome do projeto, e clique no botão de 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 em Gerenciador de Soluções, e então escolha Abrir.

  6. Na janela de XAML MainWindow.xaml de, substitua o código a seguir.

    <Window x:Class="MainWindow"
            xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="https://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>
    
    <Window x:Class="AsyncReturnTypes.MainWindow"
            xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="https://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 de Design de MainWindow.xaml.

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

  8. Substitua o código em MainWindow.xaml.vb ou em MainWindow.xaml.cs com o 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 &= String.Format("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 &= String.Format(vbCrLf & "Value of result1 variable:   {0}" & vbCrLf, result1)
            textBox1.Text &= String.Format("Value of result2 variable:   {0}" & vbCrLf, result2)
            textBox1.Text &= String.Format("Value of resultTask.Result:  {0}" & vbCrLf, integerTask.Result)
    
            ' 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 &= String.Format(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 &= String.Format(vbCrLf & "Sorry for the delay. . . ." & vbCrLf)
    
            ' This method has no return statement, so its return type is Task. 
        End Function
    
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace AsyncReturnTypes
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            // VOID EXAMPLE
            private async void button1_Click(object sender, RoutedEventArgs e)
            {
                textBox1.Clear();
    
                // Start the process and await its completion. DriverAsync is a 
                // Task-returning async method.
                await DriverAsync();
    
                // Say goodbye.
                textBox1.Text += "\r\nAll done, exiting button-click event handler.";
            }
    
            async Task DriverAsync()
            {
                // Task<T> 
                // Call and await the Task<T>-returning async method in the same statement.
                int result1 = await TaskOfT_MethodAsync();
    
                // Call and await in separate statements.
                Task<int> integerTask = TaskOfT_MethodAsync();
    
                // You can do other work that does not rely on integerTask before awaiting.
                textBox1.Text += String.Format("Application can continue working while the Task<T> runs. . . . \r\n");
    
                int result2 = await integerTask;
    
                // Display the values of the result1 variable, the result2 variable, and
                // the integerTask.Result property.
                textBox1.Text += String.Format("\r\nValue of result1 variable:   {0}\r\n", result1);
                textBox1.Text += String.Format("Value of result2 variable:   {0}\r\n", result2);
                textBox1.Text += String.Format("Value of integerTask.Result: {0}\r\n", integerTask.Result);
    
                // Task
                // Call and await the Task-returning async method in the same statement.
                await Task_MethodAsync();
    
                // Call and await in separate statements.
                Task simpleTask = Task_MethodAsync();
    
                // You can do other work that does not rely on simpleTask before awaiting.
                textBox1.Text += String.Format("\r\nApplication can continue working while the Task runs. . . .\r\n");
    
                await simpleTask;
            }
    
            // TASK<T> EXAMPLE
            async Task<int> TaskOfT_MethodAsync()
            {
                // The body of the method is expected to contain an awaited asynchronous
                // call.
                // Task.FromResult is a placeholder for actual work that returns a string.
                var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());
    
                // The method then can process the result in some way.
                int leisureHours;
                if (today.First() == 'S')
                    leisureHours = 16;
                else
                    leisureHours = 5;
    
                // Because the return statement specifies an operand of type int, the
                // method must have a return type of Task<int>.
                return leisureHours;
            }
    
    
            // TASK EXAMPLE
            async Task Task_MethodAsync()
            {
                // 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);
                // Task.Delay delays the following line by two seconds.
                textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");
    
                // This method has no return statement, so its return type is Task.  
            }
        }
    }
    
  9. Escolha a tecla F5 para executar o programa, escolha o botão de Iniciar .

    As seguintes saída devem 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

Tarefas

Passo a passo: Acessando a Web usando Async e aguardar (C# e Visual Basic)

Passo a passo: Usando o depurador com métodos assíncronos

Referência

Async (referência de C#)

Async (Visual Basic)

Aguardar o operador (Visual Basic)

aguardar (referência de C#)

FromResult<TResult>

Conceitos

Fluxo de controle em programas Async (C# e Visual Basic)