Tutorial: Acceso a web usando Async y Await (C# y Visual Basic)

Puede escribir programas asincrónicos de manera más fácil e intuitiva usando las características async/await. Puede escribir código asincrónico parecido al código sincrónico y dejar que el compilador gestione las difíciles funciones de devolución de llamada y continuaciones que normalmente implica el código asincrónico.

Para obtener más información sobre la característica asincrónica, vea Programación asincrónica con Async y Await (Visual Basic).

Este tutorial comienza con una aplicación sincrónica de Windows Presentation Foundation (WPF) que suma el número de bytes de una lista de sitios web. A continuación, el tutorial convierte la aplicación en una solución asincrónica mediante el uso de las características nuevas.

Puede desarrollar las aplicaciones completando el tutorial o descargando el ejemplo desde el explorador de ejemplo de .NET. El código de ejemplo está en el proyecto SerialAsyncExample.

En este tutorial, se realizarán las siguientes tareas:

Consulte la sección Ejemplo para obtener el ejemplo asincrónico completo.

Prerrequisitos

Debe tener Visual Studio 2012 o posterior instalado en el equipo. Para obtener más información, vea la página Visual Studio descargas.

Crear una aplicación WPF

  1. Inicie Visual Studio.

  2. En la barra de menús, elija Archivo, Nuevo, Proyecto.

    Aparece el cuadro de diálogo Nuevo proyecto .

  3. En el panel Plantillas instaladas, elija Visual Basic y, a continuación, elija Aplicación WPF en la lista de tipos de proyecto.

  4. En el cuadro de texto Nombre, escriba AsyncExampleWPF y elija el botón Aceptar.

    El proyecto nuevo aparece en el Explorador de soluciones.

Diseñar una ventana MainWindow simple de WPF

  1. En el Editor de código de Visual Studio, elija la pestaña MainWindow.xaml .

  2. Si la ventana Cuadro de herramientas no está visible, abra el menú Ver y elija Cuadro de herramientas.

  3. Agregue un control Botón y un control TextBox a la ventana MainWindow.

  4. Resalte el control TextBox y, en la ventana Propiedades, establezca los siguientes valores:

    • Establezca la propiedad Nombre en resultsTextBox.

    • Establezca la propiedad Alto en 250.

    • Establezca la propiedad Ancho en 500.

    • En la pestaña Texto, especifique una fuente monoespaciada, como Lucida Console o Global Monospace.

  5. Resalte el control Botón y, en la ventana Propiedades, establezca los siguientes valores:

    • Establezca la propiedad Nombre en startButton.

    • Cambie el valor de la propiedad Contenido de Botón a Inicio.

  6. Coloque el cuadro de texto y el botón de manera que ambos aparezcan en la ventana MainWindow.

    Para obtener más información sobre el Diseñador XAML de WPF, consulte Crear una IU con el Diseñador XAML.

Agregar una referencia

  1. En el Explorador de soluciones, resalte el nombre del proyecto.

  2. En la barra de menús, elija Proyecto, Agregar referencia.

    Aparecerá el cuadro de diálogo Administrador de referencias.

  3. En la parte superior del cuadro de diálogo, compruebe que el proyecto tiene como destino .NET Framework 4.5 o superior.

  4. En el área Ensamblados, elija Framework si no está ya seleccionado.

  5. En la lista de nombres, seleccione la casilla System.Net.Http.

  6. Elija el botón Aceptar para cerrar el cuadro de diálogo.

Agregar instrucciones Imports necesarias

  1. En Explorador de soluciones, abra el menú contextual de MainWindow.xaml.vb y, a continuación, elija Ver código.

  2. Agregue las Imports siguientes instrucciones en la parte superior del archivo de código si aún no están presentes.

    Imports System.Net.Http
    Imports System.Net
    Imports System.IO
    

Creación de una aplicación sincrónica

  1. En la ventana de diseño, MainWindow.xaml, haga doble clic en el botón Iniciar para crear el controlador de eventos en startButton_Click MainWindow.xaml.vb.

  2. En MainWindow.xaml.vb, copie el código siguiente en el cuerpo de startButton_Click :

    resultsTextBox.Clear()
    SumPageSizes()
    resultsTextBox.Text &= vbCrLf & "Control returned to startButton_Click."
    

    El código llama al método que controla la aplicación, SumPageSizes, y muestra un mensaje cuando el control vuelve a startButton_Click.

  3. El código de la solución sincrónica contiene los cuatro métodos siguientes:

    • SumPageSizes, que obtiene una lista de direcciones URL de páginas web de SetUpURLList y, a continuación, llama a GetURLContents y DisplayResults para que procesen cada dirección URL.

    • SetUpURLList, que crea y devuelve una lista de direcciones web.

    • GetURLContents, que descarga el contenido de cada sitio web y devuelve el contenido como una matriz de bytes.

    • DisplayResults, que muestra el número de bytes de la matriz de bytes de cada dirección URL.

    Copie los cuatro métodos siguientes y péguelos en el controlador startButton_Click de eventos en MainWindow.xaml.vb:

    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/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/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.
        ' Note: you can't use HttpWebRequest.GetResponse in a Windows Store app.
        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 "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub
    

Probar la solución sincrónica

  1. Presione la tecla F5 para ejecutar el programa y elija el botón Inicio .

    Debería aparecer un resultado similar a la lista siguiente:

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

    Tenga en cuenta que los recuentos tardan unos segundos en mostrarse. Durante ese tiempo, el subproceso de interfaz de usuario se bloquea mientras espera a que se descarguen los recursos solicitados. Como resultado, no se puede mover, maximizar, minimizar o ni siquiera cerrar la ventana de la pantalla después de elegir el botón Inicio. Estos intentos producirán un error hasta que empiecen a aparecer los recuentos de bytes. Si un sitio web no responde, no se le indicará cuál es el sitio que produjo el error. Incluso resulta difícil dejar de esperar y cerrar el programa.

Convertir GetURLContents en un método asincrónico

  1. Para convertir la solución sincrónica en una solución asincrónica, el mejor lugar para comenzar es en porque las llamadas al método y al método son donde la aplicación accede GetURLContents HttpWebRequest.GetResponse a la Stream.CopyTo web. .NET Framework facilita la conversión proporcionando versiones asincrónicas de ambos métodos.

    Para obtener más información sobre los modelos que se usan en GetURLContents, vea WebRequest.

    Nota

    A medida que siga los pasos de este tutorial, aparecerán varios errores del compilador. Puede hacer caso omiso y continuar con el tutorial.

    Cambie el método al que se llama en la tercera línea de GetURLContents de GetResponse al método GetResponseAsync asincrónico basado en tareas.

    Using response As WebResponse = webReq.GetResponseAsync()
    
  2. GetResponseAsync devuelve Task<TResult>. En este caso, la variable de devolución de tarea, TResult, tiene un tipo WebResponse. La tarea es una promesa para generar un objeto WebResponse real después de que se descarguen los datos solicitados y la tarea se ejecute hasta completarse.

    Para recuperar el WebResponse valor de la tarea, aplique un operador Await a la llamada a , como se muestra en el GetResponseAsync código siguiente.

    Using response As WebResponse = Await webReq.GetResponseAsync()
    

    El operador Await suspende la ejecución del método actual, GetURLContents, hasta que se complete la tarea esperada. Mientras tanto, el control devuelve al llamador del método actual. En este ejemplo, el método actual es GetURLContents y el llamador es SumPageSizes. Cuando la tarea finaliza, el objeto WebResponse prometido se genera como valor de la tarea esperada y se asigna a la variable response.

    La instrucción anterior se puede dividir en las dos instrucciones siguientes para aclarar lo que sucede.

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

    La llamada a webReq.GetResponseAsync devuelve Task(Of WebResponse) o Task<WebResponse>. A Await continuación, se aplica un operador a la tarea para recuperar el WebResponse valor.

    Si el método asincrónico debe realizar un trabajo que no depende de la finalización de la tarea, el método puede continuar con ese trabajo entre estas dos instrucciones, después de la llamada al método asincrónico y antes de que se aplique el operador await. Para obtener ejemplos, vea Cómo: Realizar varias solicitudes web en paralelo mediante Async y Await (Visual Basic) y Cómo: Extender el tutorial asincrónico mediante Task.WhenAll (Visual Basic).

  3. Dado que ha agregado el operador Await en el paso anterior, se produce un error del compilador. El operador solo se puede usar en métodos marcados con el modificador Async. Omita el error mientras repita los pasos de conversión para reemplazar la llamada a CopyTo con una llamada a CopyToAsync.

    • Cambie el nombre del método al que se llama a CopyToAsync.

    • El método CopyTo o CopyToAsync copia bytes a su argumento, content, y no devuelve un valor significativo. En la versión sincrónica, la llamada a CopyTo es una sencilla instrucción que no devuelve un valor. La versión asincrónica, CopyToAsync, devuelve una Task. La tarea funciona como "Task(void)" y permite que se espere al método. Aplique Await o await a la llamada a CopyToAsync, como se muestra en el código siguiente.

      Await responseStream.CopyToAsync(content)
      

      La instrucción anterior abrevia las dos líneas de código siguientes.

      ' 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
      
  4. Lo único que queda por hacer en GetURLContents es ajustar la firma del método. Solo puede usar el Await operador en métodos marcados con el modificador Async. Agregue el modificador para marcar el método como método asincrónico, como se muestra en el código siguiente.

    Private Async Function GetURLContents(url As String) As Byte()
    
  5. El tipo de valor devuelto de un método asincrónico solo puede ser Task , Task<TResult> . En Visual Basic, el método debe ser Function, que devuelve Task o Task(Of T), o el método debe ser Sub. Normalmente, un Sub método solo se usa en un controlador de eventos asincrónicos, donde Sub es necesario. En otros casos, se usa si el método completado tiene una instrucción Return que devuelve un valor de tipo T y se usa si el método completado no devuelve Task(T) un valor Task significativo.

    Para obtener más información, vea Tipos de valor devuelto asincrónico (Visual Basic).

    El método GetURLContents tiene una instrucción return, y la instrucción devuelve una matriz de bytes. Por lo tanto, el tipo de valor devuelto de la versión de async es Task(T), donde T es una matriz de bytes. Realice los cambios siguientes en la firma del método:

    • Cambie el tipo de valor devuelto a Task(Of Byte()).

    • Por convención, los métodos asincrónicos tienen nombres que terminan en "Async", por lo que debe cambiar el nombre del método a GetURLContentsAsync.

    En el código siguiente se muestran estos cambios.

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

    Con estos pocos cambios, se completa la conversión de GetURLContents en un método asincrónico.

Convertir SumPageSizes en un método asincrónico

  1. Repita los pasos del procedimiento anterior para SumPageSizes. Primero, cambie la llamada a GetURLContents a una llamada asincrónica.

    • Cambie el nombre del método al que se llama de GetURLContents a GetURLContentsAsync, si aún no lo ha hecho.

    • Aplique Await a la tarea que devuelve GetURLContentsAsync para obtener el valor de la matriz de bytes.

    En el código siguiente se muestran estos cambios.

    Dim urlContents As Byte() = Await GetURLContentsAsync(url)
    

    La asignación anterior abrevia las dos líneas de código siguientes.

    ' 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
    
  2. Realice los cambios siguientes en la firma del método:

    • Marque el método con el modificador Async.

    • Agregue "Async" al nombre del método.

    • Esta vez no hay ninguna variable de devolución de tarea, T, porque no devuelve un valor SumPageSizesAsync para T. (El método no tiene ninguna Return instrucción). Sin embargo, el método debe devolver Task un para que sea awaitable. Por lo tanto, cambie el tipo de método de Sub a Function . El tipo de valor devuelto de la función es Task.

    En el código siguiente se muestran estos cambios.

    Private Async Function SumPageSizesAsync() As Task
    

    Se completa así la conversión de SumPageSizes a SumPageSizesAsync.

Convertir startButton_Click en un método asincrónico

  1. En el controlador de eventos, cambie el nombre del método llamado de SumPageSizes a SumPageSizesAsync, si aún no lo ha hecho.

  2. Dado que SumPageSizesAsync es un método asincrónico, cambie el código en el controlador de eventos para esperar el resultado.

    La llamada a SumPageSizesAsync refleja la llamada a CopyToAsync en GetURLContentsAsync. La llamada devuelve Task, no Task(T).

    Al igual que en los procedimientos anteriores, puede convertir la llamada usando una o dos instrucciones. En el código siguiente se muestran estos cambios.

    ' One-step async call.
    Await SumPageSizesAsync()
    
    ' Two-step async call.
    Dim sumTask As Task = SumPageSizesAsync()
    Await sumTask
    
  3. Para evitar volver a entrar accidentalmente en la operación, agregue la instrucción siguiente encima de startButton_Click para deshabilitar el botón Inicio.

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

    Puede volver a habilitar el botón al final del controlador de eventos.

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

    Para obtener más información sobre la reenerencia, vea Control de la reenenciaen aplicaciones asincrónicas (Visual Basic).

  4. Finalmente, agregue el modificador Async a la declaración de modo que el controlador de eventos pueda esperar SumPagSizesAsync.

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

    Normalmente, no se cambian los nombres de los controladores de eventos. El tipo de valor devuelto no se cambia a Task porque los controladores de eventos deben ser Sub procedimientos Visual Basic.

    Así se completa la conversión del proyecto de procesamiento sincrónico a asincrónico.

Probar la solución asincrónica

  1. Presione la tecla F5 para ejecutar el programa y elija el botón Inicio .

  2. Deberían aparecer resultados similares a los de la solución sincrónica. No obstante, debe tener en cuenta las siguientes diferencias.

    • No todos los resultados se producen al mismo tiempo cuando se completa el procesamiento. Por ejemplo, ambos programas contienen una línea en startButton_Click que borra el cuadro de texto. La intención es borrar el cuadro de texto entre ejecuciones si elige el botón Inicio por segunda vez, después de que haya aparecido un conjunto de resultados. En la versión sincrónica, el cuadro de texto se borra antes de que aparezcan los recuentos por segunda vez, cuando se completen las descargas y el subproceso de interfaz de usuario esté libre para llevar a cabo otro trabajo. En la versión asincrónica, el cuadro de texto se borra inmediatamente después de que se elija el botón Inicio.

    • Lo más importante es que el subproceso de interfaz de usuario no se bloquea durante las descargas. Puede mover o cambiar el tamaño de la ventana mientras se descargan, se cuentan y se muestran los recursos web. Si uno de los sitios web es lento o no responde, puede cancelar la operación eligiendo el botón Cerrar (la X en el campo de color rojo en la esquina superior derecha).

Reemplace el método GetURLContentsAsync por un .NET Framework método

  1. El .NET Framework proporciona muchos métodos asincrónicos que puede usar. Uno de ellos, el HttpClient.GetByteArrayAsync(String) método , hace lo que necesita para este tutorial. Se puede usar en lugar del método GetURLContentsAsync que creó en un procedimiento anterior.

    El primer paso es crear un HttpClient objeto en el método SumPageSizesAsync . Agregue la siguiente declaración al principio del 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}
    
  2. En SumPageSizesAsync, reemplace la llamada a su método GetURLContentsAsync con una llamada al método HttpClient.

    Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    
  3. Quite o marque como comentario el método GetURLContentsAsync que escribió.

  4. Presione la tecla F5 para ejecutar el programa y elija el botón Inicio .

    El comportamiento de esta versión del proyecto debería coincidir con el comportamiento que se describe en el procedimiento "Para probar la solución asincrónica", pero con incluso menos trabajo por su parte.

Ejemplo

A continuación se muestra el ejemplo completo de la solución asincrónica convertida que usa el método GetURLContentsAsync asincrónico. Observe que es muy parecida a la solución sincrónica original.

' 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.

            '//<snippet21>
            ' 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/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/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 "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub

End Class

El código siguiente contiene el ejemplo completo de la solución que usa el método 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/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/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 "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub

End Class

Vea también