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

Você pode escrever programas assíncronos mais facilmente e intuitiva usando os recursos que são apresentados em Visual Studio 2012.Você pode escrever código assíncrono que parece o código síncrono e deixe o compilador trate as funções e as continuações difíceis de retorno que o código assíncrono normalmente envolve.

Para obter mais informações sobre o recurso de Async, consulte Programação com Async assíncrona e esperar (C# e Visual Basic).

Inicia este passo a passo através um aplicativo síncrono do Windows Presentation Foundation (WPF) que some o número de bytes em uma lista de sites.A explicação converter o aplicativo a uma solução assíncrona usando os novos recursos.

Se você não deseja criar aplicativos você mesmo, você pode baixar de “o exemplo Async: Acessando o passo a passo da Web (C# e Visual Basic) de Exemplos de código do desenvolvedor”.

Nessa explicação passo a passo, você completa as seguintes tarefas:

  • Create a WPF application.

  • Design a simple WPF MainWindow window.

  • Add a reference.

  • Add Imports statements or using directives.

  • Create a synchronous solution.

  • Test the synchronous solution.

  • Convert GetURLContents to an asynchronous method.

  • Convert SumPageSizes to an asynchronous method.

  • Convert startButton_Click to an asynchronous method.

  • Test the asynchronous solution.

  • Replace GetURLContentsAsync with a .NET Framework method.

  • Complete Code Examples from the Walkthrough

Pré-requisitos

Visual Studio 2012 deve ser instalado no seu computador.Para obter mais informações, O site da Microsoftconsulte.

Para criar um aplicativo WPF

  1. Inicie o Visual Studio.

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

    A Caixa de diálogo Novo Projeto é exibida.

  3. No painel de Modelos Instalados , escolha Visual Basic ou Visual C#, escolha Aplicativo WPF da lista de tipos de projeto.

  4. Na caixa de texto Nome , entre em AsyncExampleWPF, escolha o botão de OK .

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

Para criar um simples MainWindow WPF

  1. No editor de códigos do Visual Studio, escolha a guia MainWindow.xaml .

  2. Se a janela de Caixa de Ferramentas não estiver visível, abra o menu de Modo de Visualização , escolha Caixa de Ferramentas.

  3. Adicionar um controle de Botão e um controle de Caixa de Texto para a janela de MainWindow .

  4. Realçar o controle de Caixa de Texto e, na janela de Propriedades , defina os seguintes valores:

    • Defina a propriedade de Nome a resultsTextBox.

    • Defina a propriedade de Altura a 250.

    • Defina a propriedade de Largura a 500.

    • Na guia de Texto , especifique uma fonte de monospaced, como o console de Lucida ou global Monospace.

  5. Realçar o controle de Botão e, na janela de Propriedades , defina os seguintes valores:

    • Defina a propriedade de Nome a o botão start.

    • Altere o valor da propriedade de Conteúdo de Botão a Iniciar.

  6. Posicionar o botão e a caixa de texto de modo que ambos apareçam na janela de MainWindow .

    Para obter mais informações sobre o designer WPF XAML, consulte Criando uma interface de usuário usando o Designer XAML.

Para adicionar uma referência

  1. Em Gerenciador de Soluções, realce o nome do seu projeto.

  2. Na barra de menus, escolha Projeto, Adicionar Referência.

    A caixa de diálogo Referenciar o gerenciador aparece.

  3. Na parte superior da caixa de diálogo, verifique se o projeto está buscando o.NET Framework 4.5.

  4. Na área de Assemblies , escolha Framework se não é escolhida.

  5. Na lista name, selecione a caixa de seleção System.Net.Http .

  6. Escolha o botão de OK para fechar a caixa de diálogo.

Para adicionar instruções imports ou diretivas necessárias de uso

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

  2. Adicione as instruções de Imports (Visual Basic) ou diretivas de using (C#) na parte superior do arquivo de código se não já estão presentes.

    Imports System.Net.Http
    Imports System.Net
    Imports System.IO
    
    using System.Net.Http;
    using System.Net;
    using System.IO;
    

Para criar um aplicativo síncrono

  1. Na janela de design, MainWindow.xaml, clique duas vezes no botão de Iniciar para criar o manipulador de eventos de startButton_Click em MainWindow.xaml.vb ou em MainWindow.xaml.cs.Como alternativa, realce o botão de Iniciar , escolha o ícone de Manipuladores de eventos para elementos selecionados na janela de Propriedades , e entre em startButton_Click na caixa de texto Clicar .

  2. Em MainWindow.xaml.vb ou em MainWindow.xaml.cs, copie o seguinte código no corpo de startButton_Click.

    resultsTextBox.Clear()
    SumPageSizes()
    resultsTextBox.Text &= vbCrLf & "Control returned to startButton_Click."
    
    resultsTextBox.Clear();
    SumPageSizes();
    resultsTextBox.Text += "\r\nControl returned to startButton_Click.";
    

    O código chama o método que resulta o aplicativo, SumPageSizes, e exibe uma mensagem quando o controle retorna a startButton_Click.

  3. O código para a solução síncrono contém os quatro métodos:

    • SumPageSizes, que é uma lista URL da Web page de SetUpURLList e então chama GetURLContents e DisplayResults para processar cada URL.

    • SetUpURLList, que faz e retorna uma lista de endereços da Web.

    • GetURLContents, que baixa o conteúdo de cada site e retorna o conteúdo como uma matriz de bytes.

    • DisplayResults, que exibe o número de bytes na matriz de bytes para cada URL.

    Copie os quatro métodos, e os cola no manipulador de eventos startButton_Click em MainWindow.xaml.vb ou em MainWindow.xaml.cs.

    Private Sub SumPageSizes()
    
        ' Make a list of web addresses.
        Dim urlList As List(Of String) = SetUpURLList()
    
        Dim total = 0
        For Each url In urlList
            ' GetURLContents returns the contents of url as a byte array.
            Dim urlContents As Byte() = GetURLContents(url)
    
            DisplayResults(url, urlContents)
    
            ' Update the total.
            total += urlContents.Length
        Next
    
        ' Display the total count for all of the web addresses.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "Total bytes returned:  {0}" & vbCrLf, total)
    End Sub
    
    
    Private Function SetUpURLList() As List(Of String)
    
        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
        Return urls
    End Function
    
    
    Private Function GetURLContents(url As String) As Byte()
    
        ' The downloaded resource ends up in the variable named content.
        Dim content = New MemoryStream()
    
        ' Initialize an HttpWebRequest for the current URL.
        Dim webReq = CType(WebRequest.Create(url), HttpWebRequest)
    
        ' Send the request to the Internet resource and wait for
        ' the response.
        Using response As WebResponse = webReq.GetResponse()
            ' Get the data stream that is associated with the specified URL.
            Using responseStream As Stream = response.GetResponseStream()
                ' Read the bytes in responseStream and copy them to content.  
                responseStream.CopyTo(content)
            End Using
        End Using
    
        ' Return the result as a byte array.
        Return content.ToArray()
    End Function
    
    
    Private Sub DisplayResults(url As String, content As Byte())
    
        ' Display the length of each website. The string format 
        ' is designed to be used with a monospaced font, such as
        ' Lucida Console or Global Monospace.
        Dim bytes = content.Length
        ' Strip off the "http://".
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub
    
    private void SumPageSizes()
    {
        // Make a list of web addresses.
        List<string> urlList = SetUpURLList(); 
    
        var total = 0;
        foreach (var url in urlList)
        {
            // GetURLContents returns the contents of url as a byte array.
            byte[] urlContents = GetURLContents(url);
    
            DisplayResults(url, urlContents);
    
            // Update the total.
            total += urlContents.Length;
        }
    
        // Display the total count for all of the web addresses.
        resultsTextBox.Text += 
            string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
    }
    
    
    private List<string> SetUpURLList()
    {
        var urls = new List<string> 
        { 
            "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
            "https://msdn.microsoft.com",
            "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
            "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
            "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
            "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
            "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
            "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
            "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
            "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
        };
        return urls;
    }
    
    
    private byte[] GetURLContents(string url)
    {
        // The downloaded resource ends up in the variable named content.
        var content = new MemoryStream();
    
        // Initialize an HttpWebRequest for the current URL.
        var webReq = (HttpWebRequest)WebRequest.Create(url);
    
        // Send the request to the Internet resource and wait for
        // the response.
        using (WebResponse response = webReq.GetResponse())
        {
            // Get the data stream that is associated with the specified URL.
            using (Stream responseStream = response.GetResponseStream())
            {
                // Read the bytes in responseStream and copy them to content.  
                responseStream.CopyTo(content);
            }
        }
    
        // Return the result as a byte array.
        return content.ToArray();
    }
    
    
    private void DisplayResults(string url, byte[] content)
    {
        // Display the length of each website. The string format 
        // is designed to be used with a monospaced font, such as
        // Lucida Console or Global Monospace.
        var bytes = content.Length;
        // Strip off the "http://".
        var displayURL = url.Replace("http://", "");
        resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
    }
    

Para testar a solução síncrono

  • Escolha a tecla F5 para executar o programa, escolha o botão de Iniciar .

    A saída parecidas com a lista a seguir devem aparecer.

    msdn.microsoft.com/library/windows/apps/br211380.aspx        383832
    msdn.microsoft.com                                            33964
    msdn.microsoft.com/en-us/library/hh290136.aspx               225793
    msdn.microsoft.com/en-us/library/ee256749.aspx               143577
    msdn.microsoft.com/en-us/library/hh290138.aspx               237372
    msdn.microsoft.com/en-us/library/hh290140.aspx               128279
    msdn.microsoft.com/en-us/library/dd470362.aspx               157649
    msdn.microsoft.com/en-us/library/aa578028.aspx               204457
    msdn.microsoft.com/en-us/library/ms404677.aspx               176405
    msdn.microsoft.com/en-us/library/ff730837.aspx               143474
    
    Total bytes returned:  1834802
    
    Control returned to startButton_Click.
    

    Observe que usam alguns segundos para exibir as pontuações.Durante esse tempo, o encadeamento de interface do usuário é bloqueado quando esperar recursos aplicativos para baixar.Como resultado, você não pode mover, minimizar, maximizar, ou mesmo feche a janela de exibição depois que você escolher o botão de Iniciar .Esses esforços até o início de resultados de byte não aparecem.Se um site não está respondendo, você não tem nenhuma indicando que o site falhou.É difícil mesmo parar de espera e fechar o programa.

    Compare esse comportamento a Exemplo a uma solução assíncrono.

Para converter GetURLContents a um método assíncrono

  1. Para converter a solução a uma solução síncrona e assíncrona, o melhor lugar para começar é em GetURLContents porque chamadas para o método GetResponse de HttpWebRequest e o método CopyTo de Stream são onde o aplicativo acessa Web.O .NET Framework faz coversão fácil fornecendo versões assíncronas de ambos os métodos.

    Para obter mais informações sobre métodos que são usados em GetURLContents, consulte WebRequest.

    ObservaçãoObservação

    Porque siga as etapas nessa explicação passo a passo, vários erros de compilador aparecem.Você pode ignorar-los e continuar com a explicação passo a passo.

    Modificar o método que é chamado na terceira linha de GetURLContents de GetResponse para o método assíncrono, chave com base de GetResponseAsync .

    Using response As WebResponse = webReq.GetResponseAsync()
    
    using (WebResponse response = webReq.GetResponseAsync())
    
  2. GetResponseAsync retorna Task<TResult>.Nesse caso, a variável de retorno de tarefas, TResult, tem o tipo WebResponse.A tarefa é uma promessa de gerar um objeto real de WebResponse após os dados foram baixados aplicativos e executar a tarefa para a conclusão.

    Para recuperar o valor de WebResponse de tarefas, aplicar um operador de Espere (Visual Basic) ou de espere (C#) a chamada a GetResponseAsync, como o código a seguir mostra.

    Using response As WebResponse = Await webReq.GetResponseAsync()
    
    using (WebResponse response = await webReq.GetResponseAsync())
    

    O operador de espera suspende a execução do método atual, GetURLContents, até a tarefa esperada é concluída.Entretanto, o controle retorna para o chamador do método atual.Nesse exemplo, o método atual é GetURLContents, e o chamador é SumPageSizes.Quando a tarefa é concluída, o objeto prometido de WebResponse é gerado como o valor da tarefa esperada e atribuído a responsevariável.

    A declaração anterior pode ser separada nas duas instruções para esclarecer o que acontece.

    'Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync()
    'Using response As WebResponse = Await responseTask
    
    //Task<WebResponse> responseTask = webReq.GetResponseAsync();
    //using (WebResponse response = await responseTask)
    

    A chamada a webReq.GetResponseAsync retorna Task(Of WebResponse) ou Task<WebResponse>.Um operador de espera é aplicado à tarefa recuperar o valor de WebResponse .

    Se o método de async tem a fazer o trabalho que não depende da conclusão da tarefa, o método pode continuar com o trabalho entre essas duas declarações, após a chamada ao método de async e antes que o operador de espera é aplicado.Por exemplo, consulte Como: fazer solicitações da Web de vários em paralelo (C# e Visual Basic) e Como: estende o passo a passo usando Task.WhenAll (C# e Visual Basic).

  3. Porque você adicionou o operador de Await ou de await na etapa anterior, um erro do compilador ocorre.O operador pode ser usado apenas em métodos que são marcados com o modificador de Async (Visual Basic) ou de async (C#).Ignore o erro quando você repita as etapas de conversão para substituir a chamada a CopyTo com uma chamada a CopyToAsync.

    • Altere o nome do método que é chamado a CopyToAsync.

    • O método de CopyTo ou de CopyToAsync copia bytes para o argumento, content, e não retorna um valor significativo.Na versão síncrono, a chamada a CopyTo é uma declaração simples que não retorna um valor.A versão assíncrona, CopyToAsync, retorna Task.Funções de tarefas como “tarefa (vácuo)” e permitem que um método a ser esperado.Aplicar Await ou await a chamada a CopyToAsync, como o código a seguir mostra.

      Await responseStream.CopyToAsync(content)
      
      await responseStream.CopyToAsync(content);
      

      A declaração anterior abrevia as duas linhas de código.

      ' CopyToAsync returns a Task, not a Task<T>.
      'Dim copyTask As Task = responseStream.CopyToAsync(content)
      
      ' When copyTask is completed, content contains a copy of
      ' responseStream.
      'Await copyTask
      
      // CopyToAsync returns a Task, not a Task<T>.
      //Task copyTask = responseStream.CopyToAsync(content);
      
      // When copyTask is completed, content contains a copy of
      // responseStream.
      //await copyTask;
      
  4. Tudo que resta ser feito em GetURLContents é ajustar a assinatura de método.Você pode usar o operador de Await ou de await somente em métodos que são marcados com o modificador de Async (Visual Basic) ou de async (C#).Adicione o modificador para marcar o método como um método de async, como o código a seguir mostra.

    Private Async Function GetURLContents(url As String) As Byte()
    
    private async byte[] GetURLContents(string url)
    
  5. O tipo de retorno de um método de async só pode ser Task, Task<TResult>, ou void C#.Em Visual Basic, o método deve ser Function que retorna Task ou Task(Of T), ou o método deve ser Sub.Normalmente, um método de Sub (Visual Basic) ou um tipo de retorno de void (C#) são usados somente em um manipulador de eventos de async, onde Sub ou void sejam necessários.Em outros casos, você usa Task(T) se o método completed o tem uma instrução de Retorno ou de retorno que retorna um valor de tipo T, e uso Task se o método completed não retorna um valor significativo.Você pode pensar no tipo de retorno de Task como o significado “tarefa (o vácuo)”.

    Para obter mais informações, consulte Tipos de retorno de Async (C# e Visual Basic).

    O método GetURLContents tem uma instrução de retorno, e a declaração retorna uma matriz de bytes.Portanto, o tipo de retorno da versão de async é a tarefa (T), onde T é uma matriz de bytes.Faça as seguintes alterações na assinatura de método:

    • Altere o tipo de retorno a Task(Of Byte()) (Visual Basic) ou a Task<byte[]> (C#).

    • Por convenção, os métodos assíncronos têm nomes que terminam em “Async,” portanto renomear o método GetURLContentsAsync.

    O código a seguir mostra essas alterações.

    Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())
    
    private async Task<byte[]> GetURLContentsAsync(string url)
    

    Com poucas essas alterações, a conversão de GetURLContents a um método assíncrono é concluída.

Para converter SumPageSizes a um método assíncrono

  1. Repita as etapas do procedimento anterior para SumPageSizes.Primeiro, altere a chamada a GetURLContents a uma chamada assíncrona.

    • Altere o nome do método que é chamado de GetURLContents a GetURLContentsAsync, se você ainda não fez isso.

    • Aplicar Await ou await a tarefa que os retornos de GetURLContentsAsync para obter o valor de matriz de bytes.

    O código a seguir mostra essas alterações.

    Dim urlContents As Byte() = Await GetURLContentsAsync(url)
    
    byte[] urlContents = await GetURLContentsAsync(url);
    

    A atribuição anterior abrevia as duas linhas de código.

    ' GetURLContentsAsync returns a task. At completion, the task
    ' produces a byte array.
    'Dim getContentsTask As Task(Of Byte()) = GetURLContentsAsync(url)
    'Dim urlContents As Byte() = Await getContentsTask
    
    // GetURLContentsAsync returns a Task<T>. At completion, the task
    // produces a byte array.
    //Task<byte[]> getContentsTask = GetURLContentsAsync(url);
    //byte[] urlContents = await getContentsTask;
    
  2. Faça as seguintes alterações na assinatura de método:

    • Marcar o método com o modificador de Async ou de async .

    • Adicione “Async” ao nome do método.

    • Não há variáveis de retorno de tarefas, T, neste momento porque SumPageSizesAsync não retorna um valor para o T.(O método não tem nenhuma instrução de Return ou de return .) No entanto, o método deve retornar Task para ser awaitable.Portanto, siga um das seguintes alterações:

      • No Visual Basic, altere o tipo de método Sub a Function.O tipo de retorno da função é Task.

      • Em C#, altere o tipo de retorno do método de void a Task.

    O código a seguir mostra essas alterações.

    Private Async Function SumPageSizesAsync() As Task
    
    private async Task SumPageSizesAsync()
    

    A conversão de SumPageSizes a SumPageSizesAsync concluída.

Para converter o startButton_Click a um método assíncrono

  1. No manipulador de eventos, altere o nome do método chamado de SumPageSizes a SumPageSizesAsync, se você ainda não fez isso.

  2. Porque SumPageSizesAsync é um método de async, altere o código no manipulador de eventos para esperar o resultado.

    A chamada a SumPageSizesAsync espelham a chamada a CopyToAsync em GetURLContentsAsync.A chamada retorna Task, não Task(T).

    Como procedimentos anteriores, você pode converter a chamada usando uma instrução ou duas declarações.O código a seguir mostra essas alterações.

    '' One-step async call.
    Await SumPageSizesAsync()
    
    ' Two-step async call.
    'Dim sumTask As Task = SumPageSizesAsync()
    'Await sumTask
    
    // One-step async call.
    await SumPageSizesAsync();
    
    // Two-step async call.
    //Task sumTask = SumPageSizesAsync();
    //await sumTask;
    
  3. Para evitar acidentalmente reentering a operação, adicione a seguinte declaração na parte superior de startButton_Click para desativar o botão de Iniciar .

    ' Disable the button until the operation is complete.
    startButton.IsEnabled = False
    
    // Disable the button until the operation is complete.
    startButton.IsEnabled = false;
    

    Você pode reativar o botão no final do manipulador de eventos.

    ' Reenable the button in case you want to run the operation again.
    startButton.IsEnabled = True
    
    // Reenable the button in case you want to run the operation again.
    startButton.IsEnabled = true;
    

    Para obter mais informações sobre o reentrada, consulte Tratando a reentrada em aplicativos assíncronos (C# e Visual Basic).

  4. Finalmente, adicione o modificador de Async ou de async a declaração para que o manipulador de eventos pode esperar SumPagSizesAsync.

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
    
    private async void startButton_Click(object sender, RoutedEventArgs e)
    

    Normalmente, os nomes de manipuladores de eventos não são alterados.O tipo de retorno não é alterado para Task porque manipuladores de eventos devem retornar void em C# ou ser procedimentos de Sub no Visual Basic.Portanto, o tipo de retorno a Task.

    A conversão de projeto para processamento síncrona e assíncrona está completo.

Para testar a solução assíncrono

  1. Escolha a tecla F5 para executar o programa, escolha o botão de Iniciar .

  2. A saída parecidas com a saída de solução síncrono devem aparecer.No entanto, observe as seguintes diferenças.

    • Todos os resultados não surgem ao mesmo tempo, depois que o processamento é concluída.Por exemplo, ambos os programas contêm uma linha em startButton_Click que desmarque a caixa de texto.A tentativa é desmarque a caixa de texto entre executa se você escolher o botão de Iniciar por uma segunda vez, após um conjunto de resultados exibida.Na versão síncrono, a caixa de texto está desmarcada imediatamente antes que os resultados aparecem pela segunda vez, quando downloads estejam concluídos e o encadeamento de interface do usuário está livre fazer outro trabalho.Na versão assíncrona, a caixa de texto imediatamente limpa depois que você escolher o botão de Iniciar .

    • Mais importante, o encadeamento de interface de usuário não está bloqueado durante downloads.Você pode mover ou redimensionar a janela quando os recursos Web são baixados, contados, e exibidos.Se um dos sites é lento ou não responder, você pode cancelar a operação escolhendo o botão de Fechar (o x vermelho no campo no canto superior direito).

Para substituir o método GetURLContentsAsync com um método do .NET Framework

  1. O .NET Framework 4.5 fornece vários métodos de async que você pode usar.Um de eles, o método GetByteArrayAsync(String)de HttpClient , faz exatamente o que você precisa para essa explicação passo a passo.Você pode usá-lo em vez de método GetURLContentsAsync que você criou no procedimento anterior.

    A primeira etapa é criar um objeto de HttpClient no método SumPageSizesAsync.Adicione a seguinte declaração no início do método.

    ' Declare an HttpClient object and increase the buffer size. The
    ' default buffer size is 65,536.
    Dim client As HttpClient =
        New HttpClient() With {.MaxResponseContentBufferSize = 1000000}
    
    // Declare an HttpClient object and increase the buffer size. The
    // default buffer size is 65,536.
    HttpClient client =
        new HttpClient() { MaxResponseContentBufferSize = 1000000 };
    
  2. Em SumPageSizesAsync, substituir a chamada ao método de GetURLContentsAsync com uma chamada ao método de HttpClient .

    Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    
    byte[] urlContents = await client.GetByteArrayAsync(url);               
    
  3. Remova ou comente para fora o método de GetURLContentsAsync que você escreveu.

  4. Escolha a tecla F5 para executar o programa, escolha o botão de Iniciar .

    O comportamento da versão do projeto deve corresponder ao comportamento que “para testar o procedimento de solução assíncrono” descreve mas mesmo com menos esforço de você.

Exemplo

O código a seguir contém o exemplo completo de conversão de um síncrono a uma solução assíncrona usando o método assíncrona de GetURLContentsAsync que você escreveu.Observe que se assemelha com a solução original, síncrona.

' Add the following Imports statements, and add a reference for System.Net.Http.
Imports System.Net.Http
Imports System.Net
Imports System.IO

Class MainWindow

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click

        ' Disable the button until the operation is complete.
        startButton.IsEnabled = False

        resultsTextBox.Clear()

        '' One-step async call.
        Await SumPageSizesAsync()

        ' Two-step async call.
        'Dim sumTask As Task = SumPageSizesAsync()
        'Await sumTask

        resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."

        ' Reenable the button in case you want to run the operation again.
        startButton.IsEnabled = True
    End Sub


    Private Async Function SumPageSizesAsync() As Task

        ' Make a list of web addresses.
        Dim urlList As List(Of String) = SetUpURLList()

        Dim total = 0
        For Each url In urlList
            Dim urlContents As Byte() = Await GetURLContentsAsync(url)

            ' The previous line abbreviates the following two assignment statements.

            ' GetURLContentsAsync returns a task. At completion, the task
            ' produces a byte array.
            'Dim getContentsTask As Task(Of Byte()) = GetURLContentsAsync(url)
            'Dim urlContents As Byte() = Await getContentsTask

            DisplayResults(url, urlContents)

            ' Update the total.
            total += urlContents.Length
        Next

        ' Display the total count for all of the websites.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf &
                                             "Total bytes returned:  {0}" & vbCrLf, total)
    End Function


    Private Function SetUpURLList() As List(Of String)

        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
        Return urls
    End Function


    Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())

        ' The downloaded resource ends up in the variable named content.
        Dim content = New MemoryStream()

        ' Initialize an HttpWebRequest for the current URL.
        Dim webReq = CType(WebRequest.Create(url), HttpWebRequest)

        ' Send the request to the Internet resource and wait for
        ' the response.
        Using response As WebResponse = Await webReq.GetResponseAsync()

            ' The previous statement abbreviates the following two statements.

            'Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync()
            'Using response As WebResponse = Await responseTask

            ' Get the data stream that is associated with the specified URL.
            Using responseStream As Stream = response.GetResponseStream()
                ' Read the bytes in responseStream and copy them to content.  
                Await responseStream.CopyToAsync(content)

                ' The previous statement abbreviates the following two statements.

                ' CopyToAsync returns a Task, not a Task<T>.
                'Dim copyTask As Task = responseStream.CopyToAsync(content)

                ' When copyTask is completed, content contains a copy of
                ' responseStream.
                'Await copyTask
            End Using
        End Using

        ' Return the result as a byte array.
        Return content.ToArray()
    End Function


    Private Sub DisplayResults(url As String, content As Byte())

        ' Display the length of each website. The string format 
        ' is designed to be used with a monospaced font, such as
        ' Lucida Console or Global Monospace.
        Dim bytes = content.Length
        ' Strip off the "http://".
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub

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;

// Add the following using directives, and add a reference for System.Net.Http.
using System.Net.Http;
using System.IO;
using System.Net;

namespace AsyncExampleWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            // Disable the button until the operation is complete.
            startButton.IsEnabled = false;

            resultsTextBox.Clear();

            // One-step async call.
            await SumPageSizesAsync();

            // Two-step async call.
            //Task sumTask = SumPageSizesAsync();
            //await sumTask;

            resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";

            // Reenable the button in case you want to run the operation again.
            startButton.IsEnabled = true;
        }


        private async Task SumPageSizesAsync()
        {
            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();

            var total = 0;

            foreach (var url in urlList)
            {
                byte[] urlContents = await GetURLContentsAsync(url);

                // The previous line abbreviates the following two assignment statements.

                // GetURLContentsAsync returns a Task<T>. At completion, the task
                // produces a byte array.
                //Task<byte[]> getContentsTask = GetURLContentsAsync(url);
                //byte[] urlContents = await getContentsTask;

                DisplayResults(url, urlContents);

                // Update the total.          
                total += urlContents.Length;
            }
            // Display the total count for all of the websites.
            resultsTextBox.Text +=
                string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
        }


        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            };
            return urls;
        }


        private async Task<byte[]> GetURLContentsAsync(string url)
        {
            // The downloaded resource ends up in the variable named content.
            var content = new MemoryStream();

            // Initialize an HttpWebRequest for the current URL.
            var webReq = (HttpWebRequest)WebRequest.Create(url);

            // Send the request to the Internet resource and wait for
            // the response.                
            using (WebResponse response = await webReq.GetResponseAsync())

            // The previous statement abbreviates the following two statements.

            //Task<WebResponse> responseTask = webReq.GetResponseAsync();
            //using (WebResponse response = await responseTask)
            {
                // Get the data stream that is associated with the specified url.
                using (Stream responseStream = response.GetResponseStream())
                {
                    // Read the bytes in responseStream and copy them to content. 
                    await responseStream.CopyToAsync(content);

                    // The previous statement abbreviates the following two statements.

                    // CopyToAsync returns a Task, not a Task<T>.
                    //Task copyTask = responseStream.CopyToAsync(content);

                    // When copyTask is completed, content contains a copy of
                    // responseStream.
                    //await copyTask;
                }
            }
            // Return the result as a byte array.
            return content.ToArray();
        }


        private void DisplayResults(string url, byte[] content)
        {
            // Display the length of each website. The string format 
            // is designed to be used with a monospaced font, such as
            // Lucida Console or Global Monospace.
            var bytes = content.Length;
            // Strip off the "http://".
            var displayURL = url.Replace("http://", "");
            resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
        }
    }
}

O código a seguir contém o exemplo completo de solução que usa o método de HttpClient , GetByteArrayAsync.

' Add the following Imports statements, and add a reference for System.Net.Http.
Imports System.Net.Http
Imports System.Net
Imports System.IO

Class MainWindow

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click

        resultsTextBox.Clear()

        ' Disable the button until the operation is complete.
        startButton.IsEnabled = False

        ' One-step async call.
        Await SumPageSizesAsync()

        '' Two-step async call.
        'Dim sumTask As Task = SumPageSizesAsync()
        'Await sumTask

        resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."

        ' Reenable the button in case you want to run the operation again.
        startButton.IsEnabled = True
    End Sub


    Private Async Function SumPageSizesAsync() As Task

        ' Declare an HttpClient object and increase the buffer size. The
        ' default buffer size is 65,536.
        Dim client As HttpClient =
            New HttpClient() With {.MaxResponseContentBufferSize = 1000000}

        ' Make a list of web addresses.
        Dim urlList As List(Of String) = SetUpURLList()

        Dim total = 0
        For Each url In urlList
            ' GetByteArrayAsync returns a task. At completion, the task
            ' produces a byte array.
            Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)

            ' The following two lines can replace the previous assignment statement.
            'Dim getContentsTask As Task(Of Byte()) = client.GetByteArrayAsync(url)
            'Dim urlContents As Byte() = Await getContentsTask

            DisplayResults(url, urlContents)

            ' Update the total.
            total += urlContents.Length
        Next

        ' Display the total count for all of the websites.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf &
                                             "Total bytes returned:  {0}" & vbCrLf, total)
    End Function


    Private Function SetUpURLList() As List(Of String)

        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
        Return urls
    End Function


    Private Sub DisplayResults(url As String, content As Byte())

        ' Display the length of each website. The string format 
        ' is designed to be used with a monospaced font, such as
        ' Lucida Console or Global Monospace.
        Dim bytes = content.Length
        ' Strip off the "http://".
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub

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;

// Add the following using directives, and add a reference for System.Net.Http.
using System.Net.Http;
using System.IO;
using System.Net;


namespace AsyncExampleWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            resultsTextBox.Clear();

            // Disable the button until the operation is complete.
            startButton.IsEnabled = false;

            // One-step async call.
            await SumPageSizesAsync();

            //// Two-step async call.
            //Task sumTask = SumPageSizesAsync();
            //await sumTask;

            resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";

            // Reenable the button in case you want to run the operation again.
            startButton.IsEnabled = true;
        }


        private async Task SumPageSizesAsync()
        {
            // Declare an HttpClient object and increase the buffer size. The
            // default buffer size is 65,536.
            HttpClient client =
                new HttpClient() { MaxResponseContentBufferSize = 1000000 };

            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();

            var total = 0;

            foreach (var url in urlList)
            {
                // GetByteArrayAsync returns a task. At completion, the task
                // produces a byte array.
                byte[] urlContents = await client.GetByteArrayAsync(url);               

                // The following two lines can replace the previous assignment statement.
                //Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
                //byte[] urlContents = await getContentsTask;

                DisplayResults(url, urlContents);

                // Update the total.
                total += urlContents.Length;
            }

            // Display the total count for all of the websites.
            resultsTextBox.Text +=
                string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
        }


        private List<string> SetUpURLList()
        {
            List<string> urls = new List<string> 
            { 
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "https://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            };
            return urls;
        }


        private void DisplayResults(string url, byte[] content)
        {
            // Display the length of each website. The string format 
            // is designed to be used with a monospaced font, such as
            // Lucida Console or Global Monospace.
            var bytes = content.Length;
            // Strip off the "http://".
            var displayURL = url.Replace("http://", "");
            resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
        }
    }
}

Consulte também

Tarefas

Como: estende o passo a passo usando Task.WhenAll (C# e Visual Basic)

Como: fazer solicitações da Web de vários em paralelo (C# e Visual Basic)

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

Referência

Async (referência de C#)

aguardar (referência de C#)

Aguardar o operador (Visual Basic)

Async (Visual Basic)

Conceitos

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

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

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

Outros recursos

Exemplo de Async: Acessando o passo a passo da Web (C# e Visual Basic)

programação assíncrona chave com base (TORNEIRA)

Quickstart: usando o operador de espera para programação assíncrona