Controlar cómo se vuelve a entrar en aplicaciones asincrónicas (C# y Visual Basic)

Cuando se incluye código asincrónico en la aplicación, debería considerar y evitar posiblemente el entrar, que hace referencia a repetir una operación asincrónica antes de que se haya completado.Si no se identifica y no controla las posibilidades de entrar, puede producir resultados inesperados.

En este tema

[!NOTA]

Las instrucciones de Si revisa y ejecutando la aplicación de ejemplo muestran cómo ejecutar el código como aplicación de (WPF) de Windows Presentation Foundation o como aplicación de almacén de Windows.

Para ejecutar el ejemplo como una aplicación de WPF, debe tener Visual Studio 2012 Visual Studio Express 2012 para el escritorio de Windows, o que.NET Framework 4,5 instalado en el equipo.

Para ejecutar el ejemplo como una aplicación de Tienda Windows, debe tener Windows 8 instalado en el equipo.Además, si desea ejecutar el ejemplo desde Visual Studio, también debe tener Visual Studio 2012 o Visual Studio Express 2012 para Windows 8 instalado.

Reconocimiento de Reentrada

En el ejemplo de este tema, los usuarios elija un botón Inicio para iniciar una aplicación asincrónica que descargue una serie de sitio Web y calcula el número total de bytes descargados que.Una versión sincrónica de ejemplo respondería de la misma manera independientemente de cuántas veces elige un usuario el botón porque, después de la primera vez, el subproceso de la interfaz de usuario omite esos eventos hasta la aplicación termina de ejecutarse.En una aplicación asincrónica, sin embargo, el subproceso de la interfaz continúa respondiendo, y puede que repita la operación asincrónica antes de que se haya completado.

El ejemplo siguiente se muestra el resultado esperado si el usuario elige el botón Inicio sólo una vez.Una lista de los sitios Web descargado aparece con el tamaño, en bytes, de cada sitio.El número total de bytes aparece en el extremo.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
7. msdn.microsoft.com                                            42972
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

Sin embargo, si el usuario elige el botón más de una vez, se invoca el controlador de eventos repetidamente, y el proceso de descarga se repite cada vez.Como resultado, varias operaciones asincrónicas se ejecutan al mismo tiempo, se interpolaciones de salida los resultados, y el número total de bytes es confuso.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
7. msdn.microsoft.com                                            42972
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
7. msdn.microsoft.com                                            42972
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
7. msdn.microsoft.com                                            42972
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

Puede revisar el código que genera esta salida adoptando el final de este tema.Puede experimentar con el código descargar la solución en el equipo local y después ejecutar el proyecto de WebsiteDownload o mediante el código al final de este tema para crear dispone del proyecto para obtener más información e instrucciones, vea Si revisa y ejecutando la aplicación de ejemplo.

Administrar Reentrada

Puede administrar reentrada de diversas maneras, dependiendo de lo que la aplicación hacer.Este tema muestra los ejemplos siguientes:

  • Deshabilita el Botón Start

    Deshabilita el botón Inicio mientras la operación se ejecuta de forma que el usuario no pueda interrumpirla.

  • Cancelar y se reinicia la operación

    Cancelar cualquier operación que todavía está en ejecución cuando el usuario elige el botón Inicio de nuevo y, a continuación permite la operación recientemente solicitada continuar.

  • Operaciones y cola de Varias run salida

    Permite que todas las operaciones solicitadas se ejecutan de forma asincrónica, pero coordine la salida de modo que los resultados de cada operación aparezcan juntos y en orden.

JJ651641.collapse_all(es-es,VS.110).gifDeshabilita el Botón Start

Puede bloquear el botón Inicio mientras una operación está ejecutando deshabilitar el botón en la parte superior del controlador de eventos StartButton_Click.Después puede volver a habilitar el botón dentro de finally bloqueado cuando la operación finaliza de manera que los usuarios puedan ejecutar la aplicación.

El código siguiente muestra estos cambios, marcados con asteriscos.Puede agregar los cambios en el código al final de este tema, o puede descargar la aplicación acabada de Ejemplos de Async: Entrar en aplicaciones de escritorio de .NET o Ejemplos de Async: Entrar en aplicaciones de almacén de Windows.El nombre de proyecto es DisableStartButton.

Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
    ' This line is commented out to make the results clearer in the output.
    'ResultsTextBox.Text = ""

    ' ***Disable the Start button until the downloads are complete. 
    StartButton.IsEnabled = False

    Try
        Await AccessTheWebAsync()

    Catch ex As Exception
        ResultsTextBox.Text &= vbCrLf & "Downloads failed."
    ' ***Enable the Start button in case you want to run the program again. 
    Finally
        StartButton.IsEnabled = True

    End Try
End Sub
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    // This line is commented out to make the results clearer in the output.
    //ResultsTextBox.Text = "";

    // ***Disable the Start button until the downloads are complete. 
    StartButton.IsEnabled = false; 

    try
    {
        await AccessTheWebAsync();
    }
    catch (Exception)
    {
        ResultsTextBox.Text += "\r\nDownloads failed.";
    }
    // ***Enable the Start button in case you want to run the program again. 
    finally
    {
        StartButton.IsEnabled = true;
    }
}

Como resultado de los cambios, el botón no responde mientras AccessTheWebAsync está descargando los sitios Web, por lo que el proceso no se puede repetir.

JJ651641.collapse_all(es-es,VS.110).gifCancelar y se reinicia la operación

En lugar de deshabilitar el botón Inicio, puede conservar el activo del botón pero, si el usuario elige ese botón otra vez, cancelar la operación que está ejecutando y permite ya la operación recientemente inició continuar.

Para obtener más información sobre la cancelación, vea Ajustar la aplicación Async.

Para configurar este escenario, realice los cambios siguientes en el código básico que se proporciona en Si revisa y ejecutando la aplicación de ejemplo.También puede descargar la aplicación acabada de Ejemplos de Async: Entrar en aplicaciones de escritorio de .NET o Ejemplos de Async: Entrar en aplicaciones de almacén de Windows.El nombre de este proyecto es CancelAndRestart.

  1. Declare una variable de CancellationTokenSource, cts, que está en el ámbito para todos los métodos.

    Class MainWindow // Or Class MainPage
    
        ' *** Declare a System.Threading.CancellationTokenSource.
        Dim cts As CancellationTokenSource
    
    public partial class MainWindow : Window   // Or class MainPage
    {
        // *** Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;
    
  2. En StartButton_Click, determine si una operación ya está en curso.Si el valor de cts es null (Nothing en Visual Basic), no hay ninguna operación ya activo.Si el valor no es null, la operación que está ejecutando se cancela.

    ' *** If a download process is already underway, cancel it.
    If cts IsNot Nothing Then
        cts.Cancel()
    End If
    
    // *** If a download process is already underway, cancel it.
    if (cts != null)
    {
        cts.Cancel();
    }
    
  3. Establezca cts a un valor diferente que representa el proceso actual.

    ' *** Now set cts to cancel the current process if the button is chosen again.
    Dim newCTS As CancellationTokenSource = New CancellationTokenSource()
    cts = newCTS
    
    // *** Now set cts to a new value that you can use to cancel the current process
    // if the button is chosen again.
    CancellationTokenSource newCTS = new CancellationTokenSource();
    cts = newCTS;
    
  4. Al final de StartButton_Click, el proceso actual se completa, establezca en el valor de cts a null.

    ' *** When the process completes, signal that another process can proceed.
    If cts Is newCTS Then
        cts = Nothing
    End If
    
    // *** When the process is complete, signal that another process can begin.
    if (cts == newCTS)
        cts = null;
    

El código siguiente muestra todos los cambios en StartButton_Click.Las adiciones se marcan con asteriscos.

Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)

    ' This line is commented out to make the results clearer. 
    'ResultsTextBox.Text = ""


    ' *** If a download process is underway, cancel it.
    If cts IsNot Nothing Then
        cts.Cancel()
    End If

    ' *** Now set cts to cancel the current process if the button is chosen again.
    Dim newCTS As CancellationTokenSource = New CancellationTokenSource()
    cts = newCTS

    Try
        ' *** Send a token to carry the message if the operation is canceled.
        Await AccessTheWebAsync(cts.Token)
        

    Catch ex As OperationCanceledException
        ResultsTextBox.Text &= vbCrLf & "Download canceled." & vbCrLf

    Catch ex As Exception
        ResultsTextBox.Text &= vbCrLf & "Downloads failed."
    End Try

    ' *** When the process is complete, signal that another process can proceed.
    If cts Is newCTS Then
        cts = Nothing
    End If
End Sub
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    // This line is commented out to make the results clearer in the output.
    //ResultsTextBox.Clear();

    // *** If a download process is already underway, cancel it.
    if (cts != null)
    {
        cts.Cancel();
    }

    // *** Now set cts to cancel the current process if the button is chosen again.
    CancellationTokenSource newCTS = new CancellationTokenSource();
    cts = newCTS;

    try
    {
        // ***Send cts.Token to carry the message if there is a cancellation request.
        await AccessTheWebAsync(cts.Token);
        
    }
    // *** Catch cancellations separately.
    catch (OperationCanceledException)
    {
        ResultsTextBox.Text += "\r\nDownloads canceled.\r\n";
    }
    catch (Exception)
    {
        ResultsTextBox.Text += "\r\nDownloads failed.\r\n";
    }
    // *** When the process is complete, signal that another process can proceed.
    if (cts == newCTS)
        cts = null;
}

En AccessTheWebAsync, realice los cambios siguientes.

  • Agregue un parámetro acepte el token de cancelación de StartButton_Click.

  • Utilice el método de GetAsync para descargar los sitios Web porque GetAsync acepta un argumento de CancellationToken.

  • Antes de llamar a DisplayResults para mostrar los resultados para cada sitio Web descargado, ct comprobará para comprobar que la operación actual no ha cancelado.

El código siguiente muestra estos cambios, marcados con asteriscos.

' *** Provide a parameter for the CancellationToken from StartButton_Click.
Private Async Function AccessTheWebAsync(ct As CancellationToken) As Task

    ' Declare an HttpClient object.
    Dim client = New HttpClient()

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

    Dim total = 0
    Dim position = 0

    For Each url In urlList
        ' *** Use the HttpClient.GetAsync method because it accepts a 
        ' cancellation token.
        Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)

        ' *** Retrieve the website contents from the HttpResponseMessage.
        Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()

        ' *** Check for cancellations before displaying information about the 
        ' latest site. 
        ct.ThrowIfCancellationRequested()

        position += 1
        DisplayResults(url, urlContents, position)

        ' 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:  " & total & vbCrLf)
End Function
// *** Provide a parameter for the CancellationToken from StartButton_Click.
async Task AccessTheWebAsync(CancellationToken ct)
{
    // Declare an HttpClient object.
    HttpClient client = new HttpClient();

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

    var total = 0;
    var position = 0;

    foreach (var url in urlList)
    {
        // *** Use the HttpClient.GetAsync method because it accepts a 
        // cancellation token.
        HttpResponseMessage response = await client.GetAsync(url, ct);

        // *** Retrieve the website contents from the HttpResponseMessage.
        byte[] urlContents = await response.Content.ReadAsByteArrayAsync();

        // *** Check for cancellations before displaying information about the 
        // latest site. 
        ct.ThrowIfCancellationRequested();

        DisplayResults(url, urlContents, ++position);

        // 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);
}   

Si elige el botón Inicio varias veces durante esta aplicación se está ejecutando, debe generar resultados que son similares al siguiente resultado.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               122505
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
Download canceled.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
Download canceled.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
7. msdn.microsoft.com                                            42972
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

Para eliminar las listas parciales, quite la primera línea de código en StartButton_Click para borrar el cuadro de texto cada vez que el usuario reinicia la operación.

JJ651641.collapse_all(es-es,VS.110).gifOperaciones y cola de Varias run salida

Este tercer ejemplo es más complicado en que la aplicación se inicia otra operación asincrónica cada vez que el usuario elija el botón Inicio, y todas las operaciones ejecutadas a completarse.Todas las operaciones solicitadas descargan los sitios Web de la lista de forma asincrónica, pero muestran el resultado de las operaciones secuencialmente.Es decir, la actividad real de transferencia se intercala, como salida en Reconocimiento de Reentrada muestra, pero la lista de resultados para cada grupo se muestra por separado.

Las operaciones comparten Task global, pendingWork, que actúa como equipo selector del proceso de la pantalla.

Puede ejecutar este ejemplo pegando los cambios en el código de Compilar la aplicación, o puede seguir las instrucciones de Descargar la aplicación de descargar el ejemplo y después de ejecutar el proyecto de QueueResults.

El resultado siguiente muestra el resultado si el usuario elige el botón Inicio sólo una vez.La etiqueta de la letra, A, indica que el resultado es de botón Inicio está elegido por primera vez.Los números muestran el orden de las direcciones URL en la lista de destinos de descarga.

#Starting group A.
#Task assigned for group A.

A-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
A-2. msdn.microsoft.com/en-us/library/aa578028.aspx               209858
A-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
A-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
A-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71260
A-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186
A-7. msdn.microsoft.com                                            53266
A-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148020

TOTAL bytes returned:  918876


#Group A is complete.

Si el usuario elige el botón Inicio tres veces, ésta genera la salida que se parece a las líneas siguientes.Las líneas de información que comienzan con un signo de número (#) sigue paso a paso el progreso de la aplicación.

#Starting group A.
#Task assigned for group A.

A-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
A-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089
A-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
A-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
A-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71259
A-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199185

#Starting group B.
#Task assigned for group B.

A-7. msdn.microsoft.com                                            53266

#Starting group C.
#Task assigned for group C.

A-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010

TOTAL bytes returned:  916095

B-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
B-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089
B-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
B-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
B-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71260
B-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186

#Group A is complete.

B-7. msdn.microsoft.com                                            53266
B-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010

TOTAL bytes returned:  916097

C-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
C-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089

#Group B is complete.

C-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
C-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
C-5. msdn.microsoft.com/en-us/library/hh524395.aspx                72765
C-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186
C-7. msdn.microsoft.com                                            56190
C-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010

TOTAL bytes returned:  920526

#Group C is complete.

B y c de grupos comienzan antes de que el grupo A finalice, pero la salida de cada grupo aparece por separado.Todos los resultados del grupo A aparece primero, seguido por todos los resultados para b de grupo y, a continuación toda la salida del grupo C.La aplicación muestra siempre grupos en orden y, para cada grupo, siempre muestra información sobre los sitios Web individuales en el orden en que las direcciones URL aparecen en la lista de direcciones URL.

Sin embargo, no puede predecir el orden en que las descargas se realmente.Una vez iniciado varios grupos, las tareas de descarga que generan son todas activo.No se puede suponer que el A-1 se descargará antes de B-1, y no puede suponer que el A-1 se descargará antes de A-2.

JJ651641.collapse_all(es-es,VS.110).gifDefiniciones globales

El código muestra contiene las dos declaraciones globales siguientes que son visibles de todos los métodos.

Class MainWindow    ' Class MainPage in Windows Store app.

    ' ***Declare the following variables where all methods can access them. 
    Private pendingWork As Task = Nothing
    Private group As Char = ChrW(AscW("A") - 1)
public partial class MainWindow : Window  // Class MainPage in Windows Store app.
{
    // ***Declare the following variables where all methods can access them. 
    private Task pendingWork = null;   
    private char group = (char)('A' - 1);

La variable de Task, pendingWork, supervisa el proceso de presentación y evita que cualquier grupo divida la operación de presentación de otro grupo.La variable de caracteres, group, etiquetas salida de grupos diferentes para comprobar que los resultados aparecen en el orden esperado.

JJ651641.collapse_all(es-es,VS.110).gifEl controlador de eventos Click

El controlador de eventos, StartButton_Click, aumenta la letra de grupo cada vez que el usuario elija el botón Inicio.El controlador llama AccessTheWebAsync para ejecutar la operación de transferencia.

Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
    ' ***Verify that each group's results are displayed together, and that
    ' the groups display in order, by marking each group with a letter.
    group = ChrW(AscW(group) + 1)
    ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "#Starting group {0}.", group)

    Try
        ' *** Pass the group value to AccessTheWebAsync.
        Dim finishedGroup As Char = Await AccessTheWebAsync(group)

        ' The following line verifies a successful return from the download and 
        ' display procedures. 
        ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "#Group {0} is complete." & vbCrLf, finishedGroup)

    Catch ex As Exception
        ResultsTextBox.Text &= vbCrLf & "Downloads failed."

    End Try
End Sub
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    // ***Verify that each group's results are displayed together, and that
    // the groups display in order, by marking each group with a letter.
    group = (char)(group + 1);
    ResultsTextBox.Text += string.Format("\r\n\r\n#Starting group {0}.", group);

    try
    {
        // *** Pass the group value to AccessTheWebAsync.
        char finishedGroup = await AccessTheWebAsync(group);

        // The following line verifies a successful return from the download and
        // display procedures. 
        ResultsTextBox.Text += string.Format("\r\n\r\n#Group {0} is complete.\r\n", finishedGroup);
    }
    catch (Exception)
    {
        ResultsTextBox.Text += "\r\nDownloads failed.";
    }
}

JJ651641.collapse_all(es-es,VS.110).gifEl método de AccessTheWebAsync

Este ejemplo divide AccessTheWebAsync en dos métodos.El primer método, AccessTheWebAsync, inicia todas las tareas de descarga para un grupo y coloque pendingWork para controlar el proceso de la pantalla.El método utiliza una consulta de language Integrated query (consulta LINQ) y ToArray<TSource> para iniciar todas las tareas de descarga al mismo tiempo.

AccessTheWebAsync llama FinishOneGroupAsync para aguardar el término de cada descarga y mostrar su longitud.

FinishOneGroupAsync devuelve una tarea asignado a pendingWork en AccessTheWebAsync.Que el valor impide la interrupción por otra operación antes de que finalice la tarea.

Private Async Function AccessTheWebAsync(grp As Char) As Task(Of Char)

    Dim client = New HttpClient()

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

    ' ***Kick off the downloads. The application of ToArray activates all the download tasks.
    Dim getContentTasks As Task(Of Byte())() =
        urlList.Select(Function(addr) client.GetByteArrayAsync(addr)).ToArray()

    ' ***Call the method that awaits the downloads and displays the results.
    ' Assign the Task that FinishOneGroupAsync returns to the gatekeeper task, pendingWork.
    pendingWork = FinishOneGroupAsync(urlList, getContentTasks, grp)

    ResultsTextBox.Text &=
        String.Format(vbCrLf & "#Task assigned for group {0}. Download tasks are active." & vbCrLf, grp)

    ' ***This task is complete when a group has finished downloading and displaying.
    Await pendingWork

    ' You can do other work here or just return.
    Return grp
End Function
private async Task<char> AccessTheWebAsync(char grp)
{
    HttpClient client = new HttpClient();

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

    // ***Kick off the downloads. The application of ToArray activates all the download tasks.
    Task<byte[]>[] getContentTasks = urlList.Select(url => client.GetByteArrayAsync(url)).ToArray();

    // ***Call the method that awaits the downloads and displays the results.
    // Assign the Task that FinishOneGroupAsync returns to the gatekeeper task, pendingWork.
    pendingWork = FinishOneGroupAsync(urlList, getContentTasks, grp);

    ResultsTextBox.Text += string.Format("\r\n#Task assigned for group {0}. Download tasks are active.\r\n", grp);

    // ***This task is complete when a group has finished downloading and displaying.
    await pendingWork;

    // You can do other work here or just return.
    return grp;
}

JJ651641.collapse_all(es-es,VS.110).gifEl método de FinishOneGroupAsync

Ciclos de este método con las tareas de descarga de un grupo, esperando cada uno, que muestra la longitud del sitio Web descargado, y agregando la longitud al total.

La primera instrucción de FinishOneGroupAsync utiliza pendingWork para asegurarse de que escribir el método no interfiere con una operación que ya exista en el proceso de presentación o que está esperando ya.Si esta operación está en curso, la operación que debe esperar su turno.

Private Async Function FinishOneGroupAsync(urls As List(Of String), contentTasks As Task(Of Byte())(), grp As Char) As Task

    ' Wait for the previous group to finish displaying results.
    If pendingWork IsNot Nothing Then
        Await pendingWork
    End If

    Dim total = 0

    ' contentTasks is the array of Tasks that was created in AccessTheWebAsync.
    For i As Integer = 0 To contentTasks.Length - 1
        ' Await the download of a particular URL, and then display the URL and
        ' its length.
        Dim content As Byte() = Await contentTasks(i)
        DisplayResults(urls(i), content, i, grp)
        total += content.Length
    Next

    ' Display the total count for all of the websites.
    ResultsTextBox.Text &=
        String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned:  " & total & vbCrLf)
End Function
private async Task FinishOneGroupAsync(List<string> urls, Task<byte[]>[] contentTasks, char grp)
{
    // ***Wait for the previous group to finish displaying results.
    if (pendingWork != null) await pendingWork;

    int total = 0;

    // contentTasks is the array of Tasks that was created in AccessTheWebAsync.
    for (int i = 0; i < contentTasks.Length; i++)
    {
        // Await the download of a particular URL, and then display the URL and
        // its length.
        byte[] content = await contentTasks[i];
        DisplayResults(urls[i], content, i, grp);
        total += content.Length;
    }

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

Puede ejecutar este ejemplo pegando los cambios en el código de Compilar la aplicación, o puede seguir las instrucciones de Descargar la aplicación de descargar el ejemplo, y después de ejecutar el proyecto de QueueResults.

JJ651641.collapse_all(es-es,VS.110).gifPuntos de interés

Las líneas de información que comienzan con un signo de número (#) en la salida aclaran cómo funciona este ejemplo.

La salida muestra los modelos siguientes.

  • Un grupo puede iniciarlo como un grupo anterior muestra su resultado, pero no afectan a la presentación de salida del grupo anterior.

    #Starting group A.
    #Task assigned for group A. Download tasks are active.
    
    A-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
    A-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089
    A-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
    A-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119037
    A-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71260
    
    #Starting group B.
    #Task assigned for group B. Download tasks are active.
    
    A-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186
    A-7. msdn.microsoft.com                                            53078
    A-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010
    
    TOTAL bytes returned:  915919
    
    B-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87388
    B-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089
    B-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
    
    #Group A is complete.
    
    B-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
    B-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71260
    B-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186
    B-7. msdn.microsoft.com                                            53078
    B-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010
    
    TOTAL bytes returned:  915908
    
  • La tarea de pendingWork es null (Nothing en Visual Basic) al principio de FinishOneGroupAsync sólo para el grupo A, que inició primero.Agrupe A todavía no ha completado una expresión de aguardar cuando llega a FinishOneGroupAsync.Por consiguiente, el control no ha vuelto a AccessTheWebAsync, y la primera asignación a pendingWork no se ha producido.

  • Las dos líneas siguientes siempre aparecen juntas en la salida.El código nunca se interrumpe entre iniciar la operación de un grupo de StartButton_Click y la asignación de una tarea del grupo a pendingWork.

    #Starting group B.
    #Task assigned for group B. Download tasks are active.
    

    Después de que un grupo entre en StartButton_Click, la operación no se completa una expresión de aguardar hasta que la operación entre en FinishOneGroupAsync.Por consiguiente, ninguna otra operación puede control de ganancia durante ese segmento de código.

Si revisa y ejecutando la aplicación de ejemplo

Para comprender mejor la aplicación de ejemplo, puede descargarla, compilarlo personalmente, o revisar el código al final de este tema sin implementar la aplicación.

[!NOTA]

Para ejecutar el ejemplo como una aplicación de escritorio de (WPF) de Windows Presentation Foundation, debe tener Visual Studio 2012 Visual Studio Express 2012 para el escritorio de Windows, o que.NET Framework 4,5 instalado en el equipo.

Para ejecutar el ejemplo como una aplicación de Tienda Windows, debe tener Windows 8 instalado en el equipo.Además, si desea ejecutar el ejemplo desde Visual Studio, también debe tener Visual Studio 2012 o Visual Studio Express 2012 para Windows 8 instalado.Visual Studio 2010 no puede cargar los proyectos que van destinadas a .NET Framework 4,5.

JJ651641.collapse_all(es-es,VS.110).gifDescargar la aplicación

  1. Descargue el archivo comprimido de Ejemplos de Async: Entrar en aplicaciones de escritorio de .NET o Ejemplos de Async: Entrar en aplicaciones de almacén de Windows.

  2. Descomprima el archivo que ha descargado, y inicia Visual Studio.

  3. En la barra de menú, elija Archivo, Abrir, Proyecto/Solución.

  4. Navegue a la carpeta que contiene el código de ejemplo descomprimido, y vuelva a abrir el archivo de solución (.sln).

  5. En Explorador de soluciones, abra el menú contextual del proyecto que desea ejecutar y, a continuación Conjunto como StartUpProject.

  6. Elija las teclas CTRL+F5 para compilar y ejecutar el proyecto.

JJ651641.collapse_all(es-es,VS.110).gifCompilar la aplicación

Las secciones siguientes proporcionan el código para compilar el ejemplo como una aplicación WPF o como una aplicación de Tienda Windows.

Para compilar una aplicación WPF

  1. Inicie Visual Studio 2012.

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

    Aparece el cuadro de diálogo Nuevo proyecto.

  3. En el panel Plantillas instaladas, expanda Visual Basic o en Visual c# y, a continuación Windows.

  4. En la lista de tipos de proyecto, elija Aplicación WPF.

  5. Asigne al proyecto WebsiteDownloadWPF, y elija el botón Aceptar.

    El nuevo proyecto aparecerá en el Explorador de soluciones.

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

    Si la pestaña no está visible, abra el acceso directo de MainWindow.xaml en el Explorador de solucionesy, a continuación, elija Ver código.

  7. En la vista XAML MainWindow.xaml, reemplace el código por el código siguiente.

    <Window x:Class="MainWindow"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:WebsiteDownloadWPF"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Width="517" Height="360">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="-1,0,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="53" Background="#FFA89B9B" FontSize="36" Width="518"  />
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="-1,53,0,-36" TextWrapping="Wrap" VerticalAlignment="Top" Height="343" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="518" FontFamily="Lucida Console" />
        </Grid>
    </Window>
    
    <Window x:Class="WebsiteDownloadWPF.MainWindow"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:WebsiteDownloadWPF"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Width="517" Height="360">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="-1,0,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="53" Background="#FFA89B9B" FontSize="36" Width="518"  />
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="-1,53,0,-36" TextWrapping="Wrap" VerticalAlignment="Top" Height="343" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="518" FontFamily="Lucida Console" />
        </Grid>
    </Window>
    

    Una ventana simple que contiene un cuadro de texto y un botón aparece en la vista de Diseño de MainWindow.xaml.

  8. Agregue una referencia para System.Net.Http.

  9. En el Explorador de soluciones, abra el acceso directo de MainWindow.xaml.vb o MainWindow.xaml.cs y, a continuación, elija Código de la vista.

  10. Reemplace el código de MainWindow.xaml.vb o MainWindow.xaml.cs por el código siguiente.

    ' Add the following Imports statements, and add a reference for System.Net.Http.
    Imports System.Net.Http
    Imports System.Threading
    
    Class MainWindow
    
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
            ' This line is commented out to make the results clearer in the output.
            'ResultsTextBox.Text = ""
    
            Try
                Await AccessTheWebAsync()
    
            Catch ex As Exception
                ResultsTextBox.Text &= vbCrLf & "Downloads failed."
    
            End Try
        End Sub
    
    
        Private Async Function AccessTheWebAsync() As Task
    
            ' Declare an HttpClient object.
            Dim client = New HttpClient()
    
            ' Make a list of web addresses.
            Dim urlList As List(Of String) = SetUpURLList()
    
            Dim total = 0
            Dim position = 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)
    
                position += 1
                DisplayResults(url, urlContents, position)
    
                ' 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:  " & total & vbCrLf)
        End Function
    
    
        Private Function SetUpURLList() As List(Of String)
            Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/en-us/library/hh191443.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/jj155761.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/hh524395.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
            Return urls
        End Function
    
    
        Private Sub DisplayResults(url As String, content As Byte(), pos As Integer)
            ' 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.
    
            ' Strip off the "http:'".
            Dim displayURL = url.Replace("http://", "")
            ' Display position in the URL list, the URL, and the number of bytes.
            ResultsTextBox.Text &= String.Format(vbCrLf & "{0}. {1,-58} {2,8}", pos, displayURL, content.Length)
        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.Threading;
    
    namespace WebsiteDownloadWPF
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                // This line is commented out to make the results clearer in the output.
                //ResultsTextBox.Text = "";
    
                try
                {
                    await AccessTheWebAsync();
                }
                catch (Exception)
                {
                    ResultsTextBox.Text += "\r\nDownloads failed.";
                }
            }
    
    
            private async Task AccessTheWebAsync()
            {
                // Declare an HttpClient object.
                HttpClient client = new HttpClient();
    
                // Make a list of web addresses.
                List<string> urlList = SetUpURLList();
    
                var total = 0;
                var position = 0;
    
                foreach (var url in urlList)
                {
                    // GetByteArrayAsync returns a task. At completion, the task
                    // produces a byte array.
                    byte[] urlContents = await client.GetByteArrayAsync(url);
    
                    DisplayResults(url, urlContents, ++position);
    
                    // 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/en-us/library/hh191443.aspx",
                    "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                    "https://msdn.microsoft.com/en-us/library/jj155761.aspx",
                    "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                    "https://msdn.microsoft.com/en-us/library/hh524395.aspx",
                    "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                    "https://msdn.microsoft.com",
                    "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
                };
                return urls;
            }
    
    
            private void DisplayResults(string url, byte[] content, int pos)
            {
                // 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.
    
                // Strip off the "http://".
                var displayURL = url.Replace("http://", "");
                // Display position in the URL list, the URL, and the number of bytes.
                ResultsTextBox.Text += string.Format("\n{0}. {1,-58} {2,8}", pos, displayURL, content.Length);
            }
        }
    }
    
  11. Elija las teclas CTRL+F5 para ejecutar el programa, y elija el botón Inicio varias veces.

  12. Realice cambios de Deshabilita el Botón Start, de Cancelar y se reinicia la operación, o de Operaciones y cola de Varias run salida para administrar el reentrada.

Para compilar una aplicación de almacén de Windows

  1. Inicie Visual Studio 2012.

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

    Aparece el cuadro de diálogo Nuevo proyecto.

  3. En Instalado, categoría Plantillas, expanda Visual Basic o en Visual c# y, a continuación Tienda Windows.

  4. En la lista de tipos de proyecto, elija Aplicación en blanco (XAML).

  5. Asigne al proyecto WebsiteDownloadWin, y elija el botón Aceptar.

    El nuevo proyecto aparecerá en el Explorador de soluciones.

  6. En Explorador de soluciones, abra el menú contextual para MainPage.xaml y, a continuación Abrir.

  7. En la ventana XAML de MainPage.xaml, reemplace el código por el código siguiente.

    <Page
        x:Class="WebsiteDownloadWin.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:WebsiteDownloadWin"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" FontSize="12">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="325,77,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="145" Background="#FFA89B9B" FontSize="36" Width="711"  />
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="325,222,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="711" FontFamily="Lucida Console" />
        </Grid>
    </Page>
    

    Una ventana simple que contiene un cuadro de texto y un botón Inicio aparece en la ventana Diseñar de MainPage.xaml.

  8. En Explorador de soluciones, abra el menú contextual para MainPage.xaml.vb o MainPage.xaml.cs y, a continuación ver código.

  9. Reemplace el código de MainPage.xaml.vb o MainPage.xaml.cs con el código siguiente.

    ' Add the following Imports statements.
    Imports System.Threading.Tasks
    Imports System.Threading
    Imports System.Net.Http
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
        End Sub
    
    
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
            ' This line is commented out to make the results clearer in the output.
            'ResultsTextBox.Text = ""
    
            Try
                Await AccessTheWebAsync()
    
            Catch ex As Exception
                ResultsTextBox.Text &= vbCrLf & "Downloads failed."
    
            End Try
        End Sub
    
    
        Private Async Function AccessTheWebAsync() As Task
    
            ' Declare an HttpClient object.
            Dim client = New HttpClient()
    
            ' Make a list of web addresses.
            Dim urlList As List(Of String) = SetUpURLList()
    
            Dim total = 0
            Dim position = 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)
    
                position += 1
                DisplayResults(url, urlContents, position)
    
                ' 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:  " & total & vbCrLf)
        End Function
    
    
        Private Function SetUpURLList() As List(Of String)
            Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/en-us/library/hh191443.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/jj155761.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/hh524395.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
            Return urls
        End Function
    
    
        Private Sub DisplayResults(url As String, content As Byte(), pos As Integer)
            ' 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.
    
            ' Strip off the "http:'".
            Dim displayURL = url.Replace("http://", "")
            ' Display position in the URL list, the URL, and the number of bytes.
            ResultsTextBox.Text &= String.Format(vbCrLf & "{0}. {1,-58} {2,8}", pos, displayURL, content.Length)
        End Sub
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;
    
    // Add the following using directives. 
    using System.Threading.Tasks;
    using System.Threading;
    using System.Net.Http;
    
    
    namespace WebsiteDownloadWin
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                // This line is commented out to make the results clearer in the output.
                //ResultsTextBox.Text = "";
    
                try
                {
                    await AccessTheWebAsync();
                }
                catch (Exception)
                {
                    ResultsTextBox.Text += "\r\nDownloads failed.";
                }
            }
    
    
            private async Task AccessTheWebAsync()
            {
                // Declare an HttpClient object.
                HttpClient client = new HttpClient();
    
                // Make a list of web addresses.
                List<string> urlList = SetUpURLList();
    
                var total = 0;
                var position = 0;
    
                foreach (var url in urlList)
                {
                    // GetByteArrayAsync returns a task. At completion, the task
                    // produces a byte array.
                    byte[] urlContents = await client.GetByteArrayAsync(url);
    
                    DisplayResults(url, urlContents, ++position);
    
                    // 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/en-us/library/hh191443.aspx",
                    "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                    "https://msdn.microsoft.com/en-us/library/jj155761.aspx",
                    "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                    "https://msdn.microsoft.com/en-us/library/hh524395.aspx",
                    "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                    "https://msdn.microsoft.com",
                    "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
                };
                return urls;
            }
    
    
            private void DisplayResults(string url, byte[] content, int pos)
            {
                // 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.
    
                // Strip off the "http://".
                var displayURL = url.Replace("http://", "");
                // Display position in the URL list, the URL, and the number of bytes.
                ResultsTextBox.Text += string.Format("\n{0}. {1,-58} {2,8}", pos, displayURL, content.Length);
            }
        }
    }
    
  10. Elija las teclas CTRL+F5 para ejecutar el programa, y elija el botón Inicio varias veces.

  11. Realice cambios de Deshabilita el Botón Start, de Cancelar y se reinicia la operación, o de Operaciones y cola de Varias run salida para administrar el reentrada.

Vea también

Tareas

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

Conceptos

Programación asincrónica con Async y Await (C# y Visual Basic)

Otros recursos

Programación asincrónica (aplicaciones de almacén de Windows)

QuickStart: Llamada API asincrónico en C# o Visual Basic