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

Quando você incluir o código assíncrono em seu aplicativo, você deve considerar e possivelmente evitar o reentrada, que referencia reentering uma operação assíncrona antes de terminar.Se você não identifica e não trata possibilidades para o reentrada, pode causar resultados inesperados.

Neste tópico

ObservaçãoObservação

As instruções em Examinando e executando o aplicativo de exemplo mostram como executar o código como um aplicativo Windows Presentation Foundation (WPF) ou como um aplicativo da Windows Store.

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

Para executar o exemplo como um aplicativo de Windows Store , você deve ter o Windows 8 instalado no seu computador.Além disso, se deseja executar o exemplo do Visual Studio, também deverá ter o Visual Studio 2012 ou o Visual Studio Express 2012 for Windows 8 instalado.

Reconhecendo Reentrada

No exemplo neste tópico, os usuários escolhem um botão de Iniciar para iniciar um aplicativo assíncrono que baixa uma série de sites e calculam o número de bytes total que é baixado.Uma versão síncrono de exemplo poderia responder a mesma maneira independentemente de quantas vezes um usuário escolher o botão porque, após a primeira vez, o encadeamento de interface do usuário ignora os eventos até que o aplicativo termina de executar.Em um aplicativo assíncrono, no entanto, o encadeamento de interface do usuário continua a responder, e você pode digitar novamente a operação assíncrona antes de terminar.

O exemplo a seguir mostra a saída previstas se o usuário escolher o botão de Iniciar apenas uma vez.Uma lista de sites baixadas aparece com o tamanho, em bytes, de cada site.O número de bytes total aparece no final.

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

No entanto, se o usuário escolher o botão mais de uma vez, o manipulador de eventos é chamado repetidamente, e o processo de download reentered cada vez.Como resultado, várias operações assíncronas estão executando ao mesmo tempo, as intercalações de saída os resultados, e o número de bytes total é 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

Você pode examinar o código que produz saída essas enrolando ao final deste tópico.Você pode fazer experiências com o código fazendo a solução seu computador local e então executando o projeto de WebsiteDownload ou usando o código no final deste tópico para criar seu próprio projeto para mais informações e instruções, consulte Examinando e executando o aplicativo de exemplo.

Tratamento Reentrada

Você pode manipular o reentrada em uma variedade de maneiras, dependendo do que você deseja que seu aplicativo para fazer.Este tópico apresenta os exemplos seguintes:

  • Desativar o botão Iniciar

    Desativar o botão de Iniciar quando executar a operação de modo que o usuário não possa a quebrar.

  • Cancelar a operação e reinicie

    Cancelar qualquer operação que ainda executar quando o usuário escolher o botão de Iniciar novamente, e deixar a operação recentemente solicitada continuar.

  • Executar várias operações e coloque a saída

    Permite que todas as operações executem solicitadas de forma assíncrona, mas coordenar a exibição de saída de modo que os resultados de cada operação aparecem juntos e em ordem.

JJ651641.collapse_all(pt-br,VS.110).gifDesativar o botão Iniciar

Você pode bloquear o botão de Iniciar quando uma operação executar desativando o botão na parte superior do manipulador de eventos StartButton_Click .Você pode então reativar o botão de dentro de um bloco de finally quando concluir a operação de modo que os usuários podem executar o aplicativo novamente.

O código a seguir mostra essas alterações, que são marcadas com asteriscos.Você pode adicionar as alterações no código no final deste tópico, ou você pode baixar o aplicativo concluído de Exemplos de Async: Reentrada em aplicativos desktop .NET ou Exemplos de Async: Reentrada em aplicativos da Windows Store.O nome do projeto é 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 alterações, o botão não responde quando AccessTheWebAsync baixar sites, o processo não pode ser reentered.

JJ651641.collapse_all(pt-br,VS.110).gifCancelar a operação e reinicie

Em vez de desativar o botão de Iniciar , você pode manter o botão ativa mas, se o usuário escolher o botão novamente, cancela a operação que já está em execução e está deixando a operação recentemente iniciada continuar.

Para obter mais informações sobre o botão, consulte Ajustando seu aplicativo de Async.

Para configurar esse cenário, faça as seguintes alterações no código básico que é fornecido em Examinando e executando o aplicativo de exemplo.Você também pode baixar o aplicativo concluído de Exemplos de Async: Reentrada em aplicativos desktop .NET ou Exemplos de Async: Reentrada em aplicativos da Windows Store.O nome do projeto é CancelAndRestart.

  1. Declarar uma variável de CancellationTokenSource , cts, que está no escopo para todos os 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. Em StartButton_Click, determina se uma operação já está em andamento.Se o valor de cts é zero (Nothing no Visual Basic), nenhuma operação já está ativa.Se o valor não for zero, a operação que já está executando será cancelada.

    ' *** 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. Definir cts a um valor diferente que representa o processo atual.

    ' *** 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. No final de StartButton_Click, o processo atual está completo, então definir o valor de cts de volta para o zero.

    ' *** 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;
    

O código a seguir mostra todas as alterações em StartButton_Click.Adições são marcadas com 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;
}

Em AccessTheWebAsync, faça as seguintes alterações.

  • Adicionar um parâmetro para aceitar o símbolo de cancelamento de StartButton_Click.

  • Use o método de GetAsync para baixar sites porque GetAsync aceita um argumento de CancellationToken .

  • Antes de chamar DisplayResults para exibir os resultados para cada site baixada, verifique ct para verificar que a operação atual não seja cancelada.

O código a seguir mostra essas alterações, que são marcadas com 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);
}   

Se você escolher o botão de Iniciar várias vezes quando o aplicativo for executado, deve gerar os resultados parecidas com a seguinte saída.

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 as listas parciais, tire comentários a primeira linha de código em StartButton_Click para desmarcar a caixa de texto sempre que o usuário reinicia a operação.

JJ651641.collapse_all(pt-br,VS.110).gifExecutar várias operações e coloque a saída

Este exemplo é o terceiro mais complicado que o aplicativo é iniciado outra operação assíncrona sempre que o usuário escolha o botão de Iniciar , e todas as operações executadas para a conclusão.Todas as operações solicitadas baixar sites da lista de forma assíncrona, mas saída das operações são apresentadas em seqüência.Ou seja, a atividade real de transferência é intercalada, porque a saída em Reconhecendo Reentrada mostram, mas a lista de resultados para cada grupo é apresentada separadamente.

Operações compartilham Taskglobal, pendingWork, que serve como um porteiro para o processo de exibição.

Você pode executar este exemplo às alterações no código em Compilando o aplicativo, ou você pode seguir as instruções em Fazendo o download do aplicativo para baixar o exemplo e então executar o projeto de QueueResults.

A saída a seguir mostra o resultado se o usuário escolher o botão de Iniciar apenas uma vez.O rótulo da letra, A, indica que o resultado é o botão de Iniciar é escolhido a primeira vez.Números mostra a ordem de URL na lista de destinos de download.

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

Se o usuário escolher o botão de Iniciar três vezes, o aplicativo gera saída parecidas com as seguintes linhas.As linhas de informações que começam com um rastreamento de sustenido (#) o andamento do aplicativo.

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

O início de grupos B e o C antes que o grupo Para concluir, mas saída para cada grupo aparece separadamente.Todas as saídas para o grupo Como aparecem primeiro, seguido por todas as saídas para o grupo B e em seguida, todas as saídas para o grupo C.O aplicativo sempre exibe os grupos em ordem, e para cada grupo, sempre exibe informações sobre sites individuais na ordem que as urls aparecem na lista URL.

No entanto, você não pode prever a ordem em que downloads estão realmente.Depois que vários grupos foram enfiados, todas as tarefas de download que geram são ativos.Você não pode assumir que A-1 será baixado antes de B-1, e você não pode assumir que A-1 será baixado antes da-2.

JJ651641.collapse_all(pt-br,VS.110).gifDefinições globais

O exemplo de código contém as duas declarações globais que são visíveis para todos os 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);

A variável de Task , pendingWork, vigia o processo de exibição e impede qualquer grupo interrompa a operação de exibição de outro grupo.A variável de caracteres, group, rotula a saída de grupos diferentes para verificar que os resultados apareçam na ordem esperado.

JJ651641.collapse_all(pt-br,VS.110).gifO manipulador de eventos de clique

O manipulador de eventos, StartButton_Click, incrementos a letra do grupo sempre que o usuário escolha o botão de Iniciar .No manipulador chama AccessTheWebAsync para executar a operação de transferência.

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(pt-br,VS.110).gifO método de AccessTheWebAsync

Este exemplo AccessTheWebAsync divide em dois métodos.O primeiro método, AccessTheWebAsync, ele começa todas as tarefas de download para um grupo e definir - acima de pendingWork para controlar o processo de exibição.O método usa uma consulta consulta integrada a linguagem (LINQ) e ToArray<TSource> para iniciar qualquer download tarefas ao mesmo tempo.

AccessTheWebAsync então chama FinishOneGroupAsync para aguardar conclusão de cada download e exibir seu comprimento.

FinishOneGroupAsync retorna uma tarefa que é atribuído a pendingWork em AccessTheWebAsync.O valor que impede a interrupção por outra operação antes que a tarefa estiver concluída.

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(pt-br,VS.110).gifO método de FinishOneGroupAsync

Este método fornece um ciclo com as tarefas de download em um grupo, aguardando cada um, exibindo o comprimento do site e baixada, adicionando o comprimento total para o.

A primeira instrução em FinishOneGroupAsync usa pendingWork para certificar-se que inserir o método não interfere com uma operação que já estão em processo de exibição ou que já está esperando.Se uma operação está em andamento, a operação inserindo deve aguardar sua volta.

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

Você pode executar este exemplo arrastando as alterações no código em Compilando o aplicativo, ou você pode seguir as instruções em Fazendo o download do aplicativo para baixar o exemplo, e então executar o projeto de QueueResults.

JJ651641.collapse_all(pt-br,VS.110).gifPontos de interesse

As linhas de informações que começam com um sustenido (#) na saída de como este exemplo funciona.

A saída mostra os seguintes padrões.

  • Um grupo pode ser iniciado quando um grupo anterior exibir sua saída, mas a exibição de saída anteriores do grupo não é interrompida.

    #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
    
  • A tarefa de pendingWork éNothing nula (no Visual Basic) no início de FinishOneGroupAsync somente para o grupo de A, que iniciou primeiro.Para agrupar ainda não tiver concluído uma expressão de espera quando ele atinge FinishOneGroupAsync.Como consequência, o controle não retornou a AccessTheWebAsync, e a primeira atribuição a pendingWork não ocorreu.

  • As duas linhas sempre aparecem juntos na saída.O código é desfeito nunca entre iniciar a operação de um grupo em StartButton_Click e atribuir uma tarefa do grupo da pendingWork.

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

    Depois que um grupo entra em StartButton_Click, a operação não concluir uma expressão de espera até que a operação entre em FinishOneGroupAsync.Como consequência, nenhuma outra operação pode obter o controle durante o segmento de código.

Examinando e executando o aplicativo de exemplo

Para compreender melhor o aplicativo de exemplo, você poderá baixá-lo, compilá-lo você mesmo, ou examinar o código no final deste tópico sem implementar o aplicativo.

ObservaçãoObservação

Para executar o exemplo como um aplicativo da área de trabalho do Windows Presentation Foundation (WPF), você deve ter o Visual Studio 2012 O Visual Studio express library 2012 para a área de trabalho do Windows, ou .NET Framework 4.5 instalado no seu computador.

Para executar o exemplo como um aplicativo de Windows Store , você deve ter o Windows 8 instalado no seu computador.Além disso, se deseja executar o exemplo do Visual Studio, também deverá ter o Visual Studio 2012 ou o Visual Studio Express 2012 for Windows 8 instalado.O Visual Studio 2010 não pode carregar os projetos que são destinados para o .NET Framework 4.5.

JJ651641.collapse_all(pt-br,VS.110).gifFazendo o download do aplicativo

  1. Baixar o arquivo compactado de Exemplos de Async: Reentrada em aplicativos desktop .NET ou Exemplos de Async: Reentrada em aplicativos da Windows Store.

  2. Descompactar o arquivo que você baixou, e comece em Visual Studio.

  3. Na barra de menu, escolha Arquivo, Abrir, Projeto/solução.

  4. Navegue até a pasta que contém o código de exemplo descompactado, e abra o arquivo de solução (.sln).

  5. Em Gerenciador de Soluções, abra o menu de atalho para o projeto que você deseja executar, e então escolha Defina como StartUpProject.

  6. Escolha as teclas CTRL + f5 para compilar e executar o projeto.

JJ651641.collapse_all(pt-br,VS.110).gifCompilando o aplicativo

As seções a seguir fornecem código para criar o exemplo como um aplicativo WPF ou como um aplicativo de Windows Store .

Para criar um aplicativo WPF

  1. Inicie o Visual Studio 2012.

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

    A Caixa de diálogo Novo Projeto é exibida.

  3. No painel de Modelos Instalados , expanda Visual Basic ou **Visual C#**em seguida, expanda Janelas.

  4. Na lista de tipos de projeto, escolha Aplicativo WPF.

  5. Nomeie o projeto WebsiteDownloadWPF, e então escolha o botão de OK .

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

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

    Se a guia não estiver visível, abra o menu de atalho para MainWindow.xaml em Gerenciador de Soluções, e escolha Exibir Código.

  7. No modo de XAML de MainWindow.xaml, substitua o código com o código a seguir.

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

    Uma janela simples que contém uma caixa de texto e um botão aparece no modo de Design de MainWindow.xaml.

  8. Adicione uma referência para System.Net.Http.

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

  10. Em MainWindow.xaml.vb ou em MainWindow.xaml.cs, substitua o código com o código a seguir.

    ' 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. Escolha as teclas CTRL + f5 para executar o programa, e então escolha o botão de Iniciar várias vezes.

  12. Faça as alterações de Desativar o botão Iniciar, Cancelar a operação e reinicie, ou de Executar várias operações e coloque a saída para manipular o reentrada.

Para criar um aplicativo da Windows Store

  1. Inicie o Visual Studio 2012.

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

    A Caixa de diálogo Novo Projeto é exibida.

  3. Em Instalado, a categoria de Modelos , expanda Visual Basic ou Visual C#, e expanda Windows Store.

  4. Na lista de tipos de projeto, escolha Aplicativo em branco (XAML).

  5. Nomeie o projeto WebsiteDownloadWin, e então escolha o botão de OK .

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

  6. Em Gerenciador de Soluções, abra o menu de atalho para MainPage.xaml, escolha Abrir.

  7. Na janela de XAML de MainPage.xaml, substitua o código com o código a seguir.

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

    Uma janela simples que contém uma caixa de texto e um botão de Iniciar aparece na janela de Design de MainPage.xaml.

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

  9. Substitua o código em MainPage.xaml.vb ou em MainPage.xaml.cs com o código a seguir.

    ' 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. Escolha as teclas CTRL + f5 para executar o programa, e então escolha o botão de Iniciar várias vezes.

  11. Faça as alterações de Desativar o botão Iniciar, Cancelar a operação e reinicie, ou de Executar várias operações e coloque a saída para manipular o reentrada.

Consulte também

Tarefas

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

Conceitos

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

Outros recursos

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

Quickstart: Chamando APIs assíncrono em C# ou Visual Basic