Programação assíncrona com Async e Await (C# e Visual Basic)

É possível evitar gargalos de desempenho e aprimorar a resposta geral do seu aplicativo usando a programação assíncrona. No entanto, as técnicas tradicionais para escrever aplicativos assíncronos podem ser complicadas, dificultando sua escrita, depuração e manutenção.

O Visual Studio 2012 apresenta uma abordagem simplificada à programação assíncrona que faz uso do suporte assíncrono no .NET Framework 4.5 e no Tempo de Execução do Windows. O compilador faz o trabalho difícil que o desenvolvedor costumava fazer, e seu aplicativo mantém a estrutura lógica que se assemelha ao código síncrono. Como resultado, você obtém todas as vantagens da programação assíncrona com uma fração do esforço.

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

  • A assincronia melhora a capacidade de resposta
  • Os métodos assíncronos são mais fáceis de escrever
  • O que acontece em um método assíncrono
  • Métodos de assíncronos da API
  • Threads
  • Async e Await
  • Tipos e parâmetros de retorno
  • Convenção de nomenclatura
  • Tópicos relacionados
  • Exemplo completo
  • Tópicos relacionados

Este tópico oferece uma visão geral de quando e como usar a programação assíncrona e inclui links para tópicos de suporte que contêm detalhes e exemplos.

A assincronia melhora a capacidade de resposta

A assincronia é essencial para atividades potencialmente causadoras de bloqueios, como quando seu aplicativo acessa a Web. O acesso a um recurso da Web às vezes é lento ou atrasado. Se tal atividade for bloqueada dentro de um processo síncrono, todo o aplicativo deverá esperar. Em um processo assíncrono, o aplicativo poderá prosseguir com outro trabalho que não dependa do recurso da Web até a tarefa potencialmente causadora do bloqueio terminar.

A tabela a seguir mostra a áreas típicas onde a programação assíncrona melhora a resposta. As APIs listadas do .NET Framework 4.5 e do Tempo de Execução do Windows contêm métodos que oferecem suporte à programação assíncrona.

Área do aplicativo

APIs de suporte que contêm métodos assíncronos

Acesso à Web

HttpClient, SyndicationClient

Trabalhando com arquivos

StorageFile, StreamWriter, StreamReader, XmlReader

Trabalhando com imagens

MediaCapture, BitmapEncoder, BitmapDecoder

Programação WCF

Operações síncronas e assíncronas

A assincronia é especialmente importante para aplicativos que acessam o thread de interface de usuário porque todas as atividades relacionadas à interface do usuário normalmente compartilham um único thread. Se um processo for bloqueado em um aplicativo síncrono, todos serão bloqueados. Seu aplicativo para de responder, o que poderia levar você a concluir que ele falhou quando, na verdade, está apenas aguardando.

Quando você usa métodos assíncronos, o aplicativo continua a responder à interface do usuário. Você poderá redimensionar ou minimizar uma janela, por exemplo, ou fechar o aplicativo se você não desejar aguardar sua conclusão.

A abordagem baseada em assincronia adiciona o equivalente de uma transmissão automática à lista de opções disponíveis para escolha ao criar operações assíncronas. Ou seja, você obtém todos os benefícios da programação assíncrona tradicional, mas com muito menos esforço do desenvolvedor.

Os métodos assíncronos são mais fáceis de escrever

As palavras-chave Async e Await no Visual Basic e as palavras-chave async e await em C# são o coração da programação assíncrona. Ao usar essas duas palavras-chave, você pode usar recursos do .NET Framework ou do Tempo de Execução do Windows para criar um método assíncrono quase que tão facilmente como cria um método síncrono. Os métodos assíncronos que você define usando async e await são chamados de métodos assíncronos.

O exemplo a seguir mostra um método assíncrono. Quase tudo no código deve ser completamente familiar para você. Os comentários chamam os recursos que você deve adicionar para criar a assincronia.

O arquivo de exemplo completo pode ser encontrado no final deste tópico. Você também pode baixar o exemplo de Exemplo de assincronia: exemplo de "Programação assíncrona com Async e Await".

' Three things to note in the signature: 
'  - The method has an Async modifier.  
'  - The return type is Task or Task(Of T). (See "Return Types" section.) 
'    Here, it is Task(Of Integer) because the return statement returns an integer. 
'  - The method name ends in "Async."
Async Function AccessTheWebAsync() As Task(Of Integer)

    ' You need to add a reference to System.Net.Http to declare client. 
    Dim client As HttpClient = New HttpClient()

    ' GetStringAsync returns a Task(Of String). That means that when you await the 
    ' task you'll get a string (urlContents). 
    Dim getStringTask As Task(Of String) = client.GetStringAsync("https://msdn.microsoft.com")


    ' You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork()

    ' The Await operator suspends AccessTheWebAsync. 
    '  - AccessTheWebAsync can't continue until getStringTask is complete. 
    '  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    '  - Control resumes here when getStringTask is complete.  
    '  - The Await operator then retrieves the string result from getStringTask. 
    Dim urlContents As String = Await getStringTask

    ' The return statement specifies an integer result. 
    ' Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    Return urlContents.Length
End Function
// Three things to note in the signature: 
//  - The method has an async modifier.  
//  - The return type is Task or Task<T>. (See "Return Types" section.)
//    Here, it is Task<int> because the return statement returns an integer. 
//  - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{ 
    // You need to add a reference to System.Net.Http to declare client.
    HttpClient client = new HttpClient();

    // GetStringAsync returns a Task<string>. That means that when you await the 
    // task you'll get a string (urlContents).
    Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");

    // You can do work here that doesn't rely on the string from GetStringAsync.
    DoIndependentWork();

    // The await operator suspends AccessTheWebAsync. 
    //  - AccessTheWebAsync can't continue until getStringTask is complete. 
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
    //  - Control resumes here when getStringTask is complete.  
    //  - The await operator then retrieves the string result from getStringTask. 
    string urlContents = await getStringTask;

    // The return statement specifies an integer result. 
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
    return urlContents.Length;
}

Se AccessTheWebAsync não tiver nenhum trabalho que possa fazer entre chamar GetStringAsync e aguardar a conclusão, você poderá simplificar o código ao chamar e esperar na instrução única a seguir.

Dim urlContents As String = Await client.GetStringAsync()
string urlContents = await client.GetStringAsync();

As características a seguir resumem o que transforma o exemplo anterior em um método assíncrono.

  • A assinatura do método inclui um modificador Async ou async.

  • O nome de um método assíncrono, por convenção, termina com um sufixo "Async".

  • O tipo de retorno é um dos seguintes tipos:

    • Task se o método possui uma instrução de retorno em que o operando tem o tipo TResult.

    • Task se o método não possui instrução de retorno alguma ou se ele possui uma instrução de retorno sem operando.

    • Void (um Sub no Visual Basic) se você estiver escrevendo um manipulador de eventos assíncronos.

    Para obter mais informações, consulte “Tipos e parâmetros de retorno” mais adiante neste tópico.

  • O método geralmente inclui pelo menos uma expressão await, a qual marca um ponto onde o método não pode continuar até que a operação assíncrona aguardada seja concluída. Enquanto isso, o método é suspenso e o controle retorna para o chamador do método. A próxima seção deste tópico ilustra o que acontece no ponto de suspensão.

Em métodos assíncronos, você usa as palavras-chave e os tipos fornecidos para indicar o que deseja fazer, e o compilador faz o resto, inclusive acompanhar o que deve acontecer quando o controle retorna a um ponto de espera em um método suspenso. Alguns processos de rotina, como loops e a manipulação de exceções, podem ser difíceis de manipular em um código assíncrono tradicional. Em um método assíncrono, você escreve esses elementos da mesma forma que faria em uma solução síncrona, e o problema é resolvido.

Para obter mais informações sobre assincronia nas versões anteriores do .NET Framework, consulte TPL e programação assíncrona do .NET Framework.

O que acontece em um método assíncrono

O mais importante que você deve compreender na programação assíncrona é a forma como o fluxo de controle avança de um método para outro. O diagrama a seguir pode ser usado para conduzi-lo pelo processo.

Rastrear um programa assíncrono

Os números no diagrama correspondem às etapas a seguir.

  1. Um manipulador de eventos chama e aguarda o método assíncrono AccessTheWebAsync.

  2. AccessTheWebAsync cria uma instância de HttpClient e chama o método assíncrono GetStringAsync para baixar o conteúdo de um site como uma cadeia de caracteres.

  3. Algo acontece em GetStringAsync que suspende o andamento. Talvez ele deva aguardar o download de um site ou alguma outra atividade causadora de bloqueio. Para evitar o bloqueio de recursos, GetStringAsync transfere o controle para seu chamador, AccessTheWebAsync.

    GetStringAsync retorna um Task, em que TResult é uma cadeia de caracteres e AccessTheWebAsync atribui a tarefa à variável getStringTask. A tarefa representa o processo contínuo para a chamada a GetStringAsync, com um compromisso de produzir um valor de cadeia de caracteres real quando o trabalho estiver concluído.

  4. Como o getStringTask ainda não foi esperado, AccessTheWebAsync pode continuar com outro trabalho que não depende do resultado final de GetStringAsync. O trabalho é representado por uma chamada ao método síncrono DoIndependentWork.

  5. DoIndependentWork é um método síncrono que faz seu trabalho e retorna ao seu chamador.

  6. AccessTheWebAsync está sem trabalho que ele possa executar sem um resultado de getStringTask. Em seguida, AccessTheWebAsync deseja calcular e retornar o comprimento da cadeia de caracteres baixada, mas o método não poderá calcular o valor enquanto o método tiver a cadeia de caracteres.

    Portanto, AccessTheWebAsync usa um operador await para suspender seu andamento e para transferir o controle para o método que chamou AccessTheWebAsync. AccessTheWebAsync retorna Task(Of Integer) ou Task<int> para o chamador. A tarefa representa uma promessa de produzir um resultado inteiro que é o comprimento da cadeia de caracteres baixada.

    Observação

    Se GetStringAsync (e portanto getStringTask) for concluído antes que AccessTheWebAsync o espere, o controle permanecerá em AccessTheWebAsync.A despesa de suspender e então retornar para AccessTheWebAsync seria desperdiçada caso o processo assíncrono chamado (getStringTask) já tivesse sido concluído e AccessTheWebSync não tivesse que aguardar o resultado final.

    Dentro do chamador (manipulador de eventos neste exemplo), o processamento do padrão continua. O chamador pode fazer outro trabalho que não dependa do resultado de AccessTheWebAsync antes de aguardar o resultado, ou o chamador pode aguardar imediatamente. O manipulador de eventos está aguardando AccessTheWebAsync e AccessTheWebAsync está aguardando GetStringAsync.

  7. GetStringAsync completa e produz um resultado de cadeia de caracteres. O resultado da cadeia de caracteres não é retornado pela chamada para GetStringAsync da maneira que você poderia esperar. (Lembre-se que o método já retornou uma tarefa na etapa 3.) Em vez disso, o resultado da cadeia de caracteres é armazenado na tarefa que representa a conclusão do método, getStringTask. O operador await recupera o resultado de getStringTask. A instrução de atribuição atribui o resultado retornado a urlContents.

  8. Quando AccessTheWebAsync tem o resultado da cadeia de caracteres, o método pode calcular o comprimento da cadeia de caracteres. Em seguida, o trabalho de AccessTheWebAsync também é concluído e o manipulador de eventos de espera poderá retomar. No exemplo completo no final do tópico, é possível confirmar que o manipulador de eventos recuperou e imprimiu o valor do comprimento do resultado.

Se você não tiver experiência em programação assíncrona, considere por um minuto a diferença entre o comportamento síncrono e o assíncrono. Um método síncrono retorna quando seu trabalho é concluído (etapa 5), mas um método assíncrono retorna um valor de tarefa quando seu trabalho está suspenso (etapas 3 e 6). Quando o método assíncrono eventualmente concluir seu trabalho, a tarefa será marcada como concluída e o resultado, se houver, será armazenado na tarefa.

Para obter mais informações sobre fluxo de controle, consulte Fluxo de controle em programas assíncronos (C# e Visual Basic).

Métodos de assíncronos da API

Você pode estar curioso para saber onde encontrar métodos como GetStringAsync que oferecem suporte à programação assíncrona. O .NET Framework 4.5 contém vários membros que funcionam com async e await. É possível identificar esses membros pelo sufixo “Async” que é acrescentado ao nome do membro e um tipo de retorno de Task ou de Task. Por exemplo, a classe System.IO.Stream contém métodos como CopyToAsync, ReadAsync e WriteAsync ao lado dos métodos síncronos CopyTo, Read e Write.

O Tempo de Execução do Windows também contém vários métodos que você pode usar com async e await em aplicativos do Windows Store. Para obter mais métodos de informações e exemplo, consulte Guia de Início Rápido: Usando o operador de espera para programação assíncrona, Programação assíncrona (aplicativos da Windows Store) e WhenAny: ponte entre o .NET Framework e o Tempo de Execução do Windows (C# e Visual Basic).

Threads

Os métodos assíncronos destinam-se a ser operações não causadoras de bloqueios. Uma expressão await em um método async não bloqueia o thread atual enquanto a tarefa aguardada está em execução. Em vez disso, a expressão anterior assina o restante do método como uma continuação e retorna o controle para o chamador do método assíncrono.

As palavras-chave async e await não fazem com que threads adicionais sejam criados. Os métodos assíncronos não exigem multithreading, pois um método assíncrono não executa em seu próprio thread. O método é executado no contexto de sincronização atual e usa tempo no thread somente quando o método está ativo. É possível usar Task.Run para mover o trabalho de CPU associado a um thread em segundo plano, mas um thread em segundo plano não ajuda com um processo que está apenas aguardando que os resultados tornem-se disponíveis.

A abordagem baseada em async para a programação assíncrona é preferível às abordagens existentes em quase todos os casos. Em particular, essa abordagem é melhor do que BackgroundWorker para operações associadas a E/S porque o código é mais simples e você não precisa se proteger contra condições de corrida. Em combinação com Task.Run, a programação async é melhor do que BackgroundWorker para operações associadas à CPU porque a programação async separa os detalhes de coordenação da execução do seu código do trabalho que Task.Run transfere ao threadpool.

Async e Await

Se especificar que um método é um método assíncrono usando um modificador Async ou async, você habilitará os dois recursos a seguir.

  • O método assíncrono marcado pode usar Await ou await para designar pontos de suspensão. O operador await informa ao compilador que o método assíncrono não poderá continuar além daquele ponto até que o processo assíncrono aguardado seja concluído. Enquanto isso, o controle retorna para o chamador do método assíncrono.

    A suspensão de um método assíncrono em uma expressão await não constitui uma saída de método e os blocos de finally não são executados.

  • O método assíncrono marcado pode ele próprio ser aguardado por métodos que o chamam.

Um método assíncrono normalmente contém uma ou mais ocorrências de um operador await, mas a ausência de expressões await não causa um erro do compilador. Se um método assíncrono não usa um operador de espera para marcar um ponto de suspensão, o método é executado da mesma forma que o método síncrono, independentemente do modificador async. O compilador emite um aviso para esses métodos.

Async, async, Await e await são palavras-chave contextuais. Para obter mais informações e exemplos, consulte os seguintes tópicos:

Tipos e parâmetros de retorno

Na programação .NET Framework, um método assíncrono costuma retornar um Task ou um Task. Dentro de um método assíncrono, um operador de espera é aplicado a uma tarefa que é retornada de uma chamada para outro método assíncrono.

Você especificará Task como o tipo de retorno se o método contiver uma instrução Return (Visual Basic) ou return (C#) que especifica um operando do tipo TResult.

Você usará Task como o tipo de retorno caso o método não possua nenhuma instrução return ou tenha uma instrução return que não retorna um operando.

O exemplo a seguir mostra como você declara e chama um método que retorna um Task ou Task.

' Signature specifies Task(Of Integer)
Async Function TaskOfTResult_MethodAsync() As Task(Of Integer)

    Dim hours As Integer
    ' . . .
    ' Return statement specifies an integer result.
    Return hours
End Function

' Calls to TaskOfTResult_MethodAsync
Dim returnedTaskTResult As Task(Of Integer) = TaskOfTResult_MethodAsync()
Dim intResult As Integer = Await returnedTaskTResult
' or, in a single statement
Dim intResult As Integer = Await TaskOfTResult_MethodAsync()


' Signature specifies Task
Async Function Task_MethodAsync() As Task

    ' . . .
    ' The method has no return statement.
End Function

' Calls to Task_MethodAsync
Task returnedTask = Task_MethodAsync()
Await returnedTask
' or, in a single statement
Await Task_MethodAsync()
// Signature specifies Task<TResult>
async Task<int> TaskOfTResult_MethodAsync()
{
    int hours;
    // . . .
    // Return statement specifies an integer result.
    return hours;
}

// Calls to TaskOfTResult_MethodAsync
Task<int> returnedTaskTResult = TaskOfTResult_MethodAsync();
int intResult = await returnedTaskTResult;
// or, in a single statement
int intResult = await TaskOfTResult_MethodAsync();


// Signature specifies Task
async Task Task_MethodAsync()
{
    // . . .
    // The method has no return statement.  
}

// Calls to Task_MethodAsync
Task returnedTask = Task_MethodAsync();
await returnedTask;
// or, in a single statement
await Task_MethodAsync();

Cada tarefa retornada representa um trabalho em andamento. Uma tarefa encapsula informações sobre o estado do processo assíncrono e, consequentemente, o resultado final do processo ou a exceção que o processo apresenta quando não é bem-sucedido.

Um método assíncrono também pode ser um método Sub (Visual Basic) ou ter um tipo de retorno void (C#). Esse tipo de retorno é usado principalmente para definir manipuladores de eventos, onde o tipo de retorno void é necessário. Os manipuladores de eventos assíncronos geralmente servem como o ponto de partida para programas assíncronos.

Um método assíncrono que é um procedimento Sub ou que tem um tipo de retorno void não pode ser esperado, e o chamador de um método que retorna void não pode capturar nenhuma exceção acionada pelo método.

Um método assíncrono não pode declarar parâmetros ByRef no Visual Basic ou parâmetros ref or out no C#, mas o método pode chamar métodos que possuem esses parâmetros.

Para obter mais informações e exemplos, consulte Tipos de retorno assíncronos (C# e Visual Basic). Para obter mais informações sobre como capturar exceções nos métodos assíncronos, consulte try-catch (Referência de C#) ou Instrução Try...Catch...Finally (Visual Basic).

APIs assíncronas na programação de Tempo de Execução do Windows possuem um dos seguintes tipos de retorno, que são semelhantes às tarefas:

Para obter mais informações e um exemplo, consulte Guia de Início Rápido: Usando o operador de espera para programação assíncrona.

Convenção de nomenclatura

Por convenção, deve-se acrescentar "Async" aos nomes dos métodos que possuem um modificador Async ou async.

É possível ignorar a convenção quando um evento, uma classe base ou um contrato de interface sugere um nome diferente. Por exemplo, você não deve renomear manipuladores de eventos comuns, como Button1_Click.

Tópicos relacionados

Título

Descrição

Amostra

Instruções passo a passo: acessando a Web e usando Async e Await (C# e Visual Basic)

Mostra como converter uma solução síncrona do WPF em uma solução assíncrona do WPF. O aplicativo baixa uma série de sites.

Exemplo de assincronia: acessando o passo a passo da Web (C# e Visual Basic)

Como estender as instruções passo a passo assíncronas usando Task.WhenAll (C# e Visual Basic)

Adiciona Task.WhenAll à explicação passo a passo anterior. O uso de WhenAll inicia todos os downloads ao mesmo tempo.

Instruções passo a passo: fazer várias solicitações da Web em paralelo e usando Async e Await (C# e Visual Basic)

Demonstra como iniciar várias tarefas ao mesmo tempo.

Exemplo de assincronia: Fazer várias solicitações da Web paralelamente (C# e Visual Basic)

Tipos de retorno assíncronos (C# e Visual Basic)

Ilustra os tipos que os métodos assíncronos podem retornar e explica quando cada tipo é apropriado.

Fluxo de controle em programas assíncronos (C# e Visual Basic)

Rastreia em detalhes o fluxo de controle por meio de uma sucessão de expressões de espera em um programa assíncrono.

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

Ajustando seu aplicativo Async (C# e Visual Basic)

Mostra como adicionar a seguinte funcionalidade à sua solução assíncrona:

Exemplo de assincronia: Ajustando o aplicativo (C# e Visual Basic)

Tratando a reentrada em aplicativos assíncronos (C# e Visual Basic)

Mostra como manipular casos em que uma operação assíncrona ativa é reiniciada enquanto está em execução.

WhenAny: ponte entre o .NET Framework e o Tempo de Execução do Windows (C# e Visual Basic)

Mostra como criar uma ponte entre tipos de Tarefa no .NET Framework e IAsyncOperations no Tempo de Execução do Windows para que você possa usar o WhenAny``1 com um método Tempo de Execução do Windows.

Exemplo de assincronia: Ponte entre o .NET e o Tempo de Execução do Windows (AsTask e WhenAny)

Cancelamento assíncrono: ponte entre o .NET Framework e o Tempo de Execução do Windows (C# e Visual Basic)

Mostra como criar uma ponte entre tipos de Tarefa no .NET Framework e IAsyncOperations no Tempo de Execução do Windows para que você possa usar o CancellationTokenSource com um método Tempo de Execução do Windows.

Exemplo de assincronia: Ponte entre o .NET e o Tempo de Execução do Windows (AsTask & Cancellation)

Usando o Async para acessar arquivos (C# e Visual Basic)

Lista e demonstra as vantagens de usar async e await para acessar arquivos.

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

Demonstra o fluxo de controle em uma instrução await e o comportamento dos comandos Depuração Completa, Depuração Parcial e Depuração Circular em métodos assíncronos.

Padrão assíncrono baseado em tarefa (TAP)

Descreve um novo padrão de assincronia no .NET Framework. O padrão baseia-se nos tipos Task e Task.

Início rápido: Chamando APIs assíncronas em C# ou no Visual Basic

Mostra como usar async e await em um aplicativo do Windows Store.

Programação assíncrona (aplicativos da Windows Store)

Fornece uma visão geral da programação assíncrona no Tempo de Execução do Windows.

Vídeos sobre assincronia no Channel 9

Fornece links para uma variedade de vídeos sobre programação assíncrona.

Exemplo completo

O código a seguir é o arquivo MainWindow.xaml.vb ou MainWindow.xaml.cs do aplicativo Windows Presentation Foundation (WPF) discutido por este tópico. É possível baixar o exemplo de Exemplo de assincronia: Exemplo de "Programação assíncrona com Async e Await”.

' Add an Imports statement and a reference for System.Net.Http 
Imports System.Net.Http

Class MainWindow

    ' Mark the event handler with async so you can use Await in it. 
    Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)

        ' Call and await separately. 
        'Task<int> getLengthTask = AccessTheWebAsync(); 
        '' You can do independent work here. 
        'int contentLength = await getLengthTask; 

        Dim contentLength As Integer = Await AccessTheWebAsync()

        ResultsTextBox.Text &=
            String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, contentLength)
    End Sub 


    ' Three things to note in the signature: 
    '  - The method has an Async modifier.  
    '  - The return type is Task or Task(Of T). (See "Return Types" section.) 
    '    Here, it is Task(Of Integer) because the return statement returns an integer. 
    '  - The method name ends in "Async."
    Async Function AccessTheWebAsync() As Task(Of Integer)

        ' You need to add a reference to System.Net.Http to declare client. 
        Dim client As HttpClient = New HttpClient()

        ' GetStringAsync returns a Task(Of String). That means that when you await the 
        ' task you'll get a string (urlContents). 
        Dim getStringTask As Task(Of String) = client.GetStringAsync("https://msdn.microsoft.com")


        ' You can do work here that doesn't rely on the string from GetStringAsync.
        DoIndependentWork()

        ' The Await operator suspends AccessTheWebAsync. 
        '  - AccessTheWebAsync can't continue until getStringTask is complete. 
        '  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
        '  - Control resumes here when getStringTask is complete.  
        '  - The Await operator then retrieves the string result from getStringTask. 
        Dim urlContents As String = Await getStringTask

        ' The return statement specifies an integer result. 
        ' Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
        Return urlContents.Length
    End Function 


    Sub DoIndependentWork()
        ResultsTextBox.Text &= "Working . . . . . . ." & vbCrLf
    End Sub 
End Class 

' Sample Output: 

' Working . . . . . . . 

' Length of the downloaded string: 41763.
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;

// Add a using directive and a reference for System.Net.Http; 
using System.Net.Http;

namespace AsyncFirstExample
{
    public partial class MainWindow : Window
    {
        // Mark the event handler with async so you can use await in it. 
        private async void StartButton_Click(object sender, RoutedEventArgs e)
        {
            // Call and await separately. 
            //Task<int> getLengthTask = AccessTheWebAsync(); 
            //// You can do independent work here. 
            //int contentLength = await getLengthTask; 

            int contentLength = await AccessTheWebAsync();

            resultsTextBox.Text +=
                String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
        }


        // Three things to note in the signature: 
        //  - The method has an async modifier.  
        //  - The return type is Task or Task<T>. (See "Return Types" section.)
        //    Here, it is Task<int> because the return statement returns an integer. 
        //  - The method name ends in "Async."
        async Task<int> AccessTheWebAsync()
        { 
            // You need to add a reference to System.Net.Http to declare client.
            HttpClient client = new HttpClient();

            // GetStringAsync returns a Task<string>. That means that when you await the 
            // task you'll get a string (urlContents).
            Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");

            // You can do work here that doesn't rely on the string from GetStringAsync.
            DoIndependentWork();

            // The await operator suspends AccessTheWebAsync. 
            //  - AccessTheWebAsync can't continue until getStringTask is complete. 
            //  - Meanwhile, control returns to the caller of AccessTheWebAsync. 
            //  - Control resumes here when getStringTask is complete.  
            //  - The await operator then retrieves the string result from getStringTask. 
            string urlContents = await getStringTask;

            // The return statement specifies an integer result. 
            // Any methods that are awaiting AccessTheWebAsync retrieve the length value. 
            return urlContents.Length;
        }


        void DoIndependentWork()
        {
            resultsTextBox.Text += "Working . . . . . . .\r\n";
        }
    }
}

// Sample Output: 

// Working . . . . . . . 

// Length of the downloaded string: 41564.

Consulte também

Referência

async (Referência de C#)

await (Referência de C#)

Operador Await (Visual Basic)

Async (Visual Basic)

Outros recursos

Exemplo: Programação assíncrona .NET para aplicativos da Windows Store

Exemplo: Fazendo um cliente Web await

Exemplo (C#): Salvar uma coleção do armazenamento de aplicativo

Exemplo (Visual Basic): Salvar uma coleção do armazenamento de aplicativo