Condividi tramite


Gestione della reentrancy nelle applicazioni asincrone (C# e Visual Basic)

Quando si include il codice asincrono nell'applicazione, è necessario considerare ed eventualmente impedire il motivo, che fa riferimento a registrare nuovamente un'operazione asincrona prima che venga completato.Se non si individua e non gestite le possibilità per il motivo, può provocare risultati imprevisti.

In questo argomento

[!NOTA]

Le istruzioni in Rivisto ed eseguendo l'applicazione di esempio viene illustrato come eseguire il codice come applicazione Windows Presentation Foundation (WPF) o come le finestre dell'applicazione.

Per eseguire l'esempio come applicazione WPF, è necessario disporre di Visual Studio 2012 Visual Studio express 2012 per Windows Desktop, o .NET Framework 4,5 installato nel computer.

Per eseguire l'esempio come applicazione di Windows Store, è necessario disporre di Windows 8 installato nel computer.Inoltre, se si desidera eseguire l'esempio da Visual Studio, è necessario disporre di Visual Studio 2012 o Visual Studio express 2012 per Windows 8 installato.

Riconoscimento di Reentrancy

Nell'esempio in questo argomento, gli utenti scelgono un pulsante Avvio per avviare un'applicazione asincrona che scarica una serie di siti Web e calcola il numero totale di byte che vengano scaricati.Una versione sincrona di esempio risponderebbe la stessa modalità indipendentemente dal numero di volte in cui un utente sceglie il pulsante, perché dopo la prima volta, il thread UI ignora gli eventi finché l'applicazione non ha completato l'esecuzione.In un'applicazione asincrona, tuttavia, il thread UI continua a rispondere e potrebbe registrare nuovamente l'operazione asincrona prima che è stata completata.

Nell'esempio seguente viene mostrato l'output previsto se l'utente sceglie solo una volta sul pulsante Avvio.Un elenco di siti Web scaricati visualizzato con la dimensione, in byte, di ogni sito.Il numero totale di byte viene visualizzato alla fine.

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

Tuttavia, se l'utente sceglie più di uno volta, il gestore eventi viene chiamato ripetutamente e il processo di download si torna ogni volta.Pertanto, più operazioni asincrone in esecuzione contemporaneamente, le interfoliazioni di output i risultati e il numero totale di byte è fuorviante.

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

È possibile esaminare il codice che produce l'output scorrendo alla fine di questo argomento.È possibile sperimentare il codice in corso la soluzione nel computer locale e quindi esegue il progetto WebsiteDownload o tramite il codice alla fine di questo argomento per creare un progetto per ulteriori informazioni e istruzioni, vedere Rivisto ed eseguendo l'applicazione di esempio.

Gestione Reentrancy

È possibile gestire il motivo in diversi modi, in base alla quale l'applicazione a eseguire.Questo argomento contiene i seguenti esempi:

  • Disabilitare il pulsante Start

    Disabilitare il pulsante Avvio mentre l'operazione viene eseguita in modo che non possa essere interrotto l'utente.

  • Riavviare e annullare l'operazione

    Annullare qualsiasi operazione che è ancora in esecuzione quando l'utente sceglie sul pulsante Avvio quindi possibile l'operazione più richiesta continuare.

  • Eseguire più operazioni e mettere in coda di output

    Consentire a tutte le operazioni richieste vengano eseguite in modo asincrono, ma che coordinano la visualizzazione di output in modo che i risultati di ogni operazione di raccolta e nell'ordine.

JJ651641.collapse_all(it-it,VS.110).gifDisabilitare il pulsante Start

È possibile bloccare il pulsante Avvio durante un'operazione in esecuzione disabilitando il pulsante all'inizio del gestore eventi di StartButton_Click.È quindi possibile riabilitare il pulsante dall'interno di un blocco di finally quando l'operazione viene completata in modo da poter eseguire nuovamente gli utenti l'applicazione.

Il codice seguente vengono illustrate queste modifiche, contrassegnate con l'asterisco.È possibile aggiungere le modifiche al codice alla fine di questo argomento, oppure scaricare l'applicazione finita da Esempi di Async: Reentrancy nelle applicazioni desktop .NET o Esempi di Async: Reentrancy nelle applicazioni di archivio di Windows.Il nome del progetto è 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;
    }
}

Come conseguenza di modifiche, il pulsante non risponde durante AccessTheWebAsync lo scaricamento dei siti Web, pertanto il processo non può essere rientrato.

JJ651641.collapse_all(it-it,VS.110).gifRiavviare e annullare l'operazione

Anziché disabilitare il pulsante Avvio, è possibile mantenere attive il pulsante, ma se l'utente sceglie sul pulsante, viene annullato l'operazione già in esecuzione e consente l'operazione di recente avviata continuare.

Per ulteriori informazioni sull'annullamento, vedere Per ottimizzare l'applicazione di Async.

Per installare questo scenario, apportare le seguenti modifiche al codice di base che viene fornito in Rivisto ed eseguendo l'applicazione di esempio.È inoltre possibile scaricare l'applicazione finita da Esempi di Async: Reentrancy nelle applicazioni desktop .NET o Esempi di Async: Reentrancy nelle applicazioni di archivio di Windows.Il nome del progetto è CancelAndRestart.

  1. Dichiarare una variabile di CancellationTokenSource, cts, che nell'ambito per tutti i metodi.

    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. In StartButton_Click, determinare se un'operazione è già in corso.Se il valore di cts è null (Nothing in Visual Basic), non è già presente alcuna operazione attiva.Se il valore non è null, l'operazione già in esecuzione viene annullata.

    ' *** 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. Impostare cts su un valore diverso che rappresenta il processo corrente.

    ' *** 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. Alla fine di StartButton_Click, il processo corrente è completo, in modo da impostare il valore di cts di nuovo 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;
    

Il codice seguente mostra tutte le modifiche in StartButton_Click.Le aggiunte sono contrassegnate con l'asterisco.

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

In AccessTheWebAsync, apportare le modifiche seguenti.

  • Aggiungere un parametro accetti il token di annullamento da StartButton_Click.

  • Utilizzare il metodo di GetAsync per scaricare i siti Web perché GetAsync accetta un argomento di CancellationToken.

  • Prima di chiamare DisplayResults per visualizzare i risultati per ogni sito Web scaricato, controlli ct per verificare che l'operazione corrente non sia stata annullata.

Il codice seguente vengono illustrate queste modifiche, contrassegnate con l'asterisco.

' *** 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 si sceglie il pulsante Avvio più volte durante questa applicazione, deve produrre risultati simili al seguente output.

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

Per eliminare gli elenchi parziali, rimuovere il commento dalla prima riga di codice in StartButton_Click per rimuovere la casella di testo quando l'utente ripetere l'operazione.

JJ651641.collapse_all(it-it,VS.110).gifEseguire più operazioni e mettere in coda di output

Il terzo esempio è più complessa in quanto l'applicazione viene avviata quando un'altra operazione asincrona che l'utente sceglie il pulsante Avvio e tutte le operazioni eseguite al completamento.Tutte le operazioni richieste scaricano i siti Web dall'elenco in modo asincrono, ma l'output le operazioni è verificato in sequenza.Ovvero effettivo attività di download è interfogliata, come illustrato nell'output in Riconoscimento di Reentrancy, ma l'elenco dei risultati per ogni gruppo è verificato separatamente.

Le operazioni condividono Taskglobale, pendingWork, che funge da portiere per visualizzare il processo.

È possibile eseguire l'esempio incollando le modifiche nel codice in Compilare l'applicazioneo, è possibile seguire le istruzioni in Scaricare l'applicazione scaricare l'esempio quindi eseguire il progetto QueueResults.

Nell'output seguente viene mostrato il risultato se l'utente sceglie solo una volta sul pulsante Avvio.L'etichetta della lettera, Su, indica che il risultato è la prima volta dal pulsante Avvio viene scelto.I numeri illustrato l'ordine degli URL nell'elenco di destinazioni di 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 l'utente sceglie il pulsante Avvio tre volte, l'applicazione genera output analogo alle linee.Le righe di informazioni che iniziano con un'analisi di cancelletto (#) allo stato di avanzamento dell'applicazione.

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

I gruppi B e C inizia prima del gruppo A sia stato completato, ma l'output per ogni gruppo viene visualizzata separatamente.Tutto l'output per il gruppo A viene visualizzata per prima, seguita da tutto l'output per il gruppo B quindi da tutto l'output per il gruppo C.Viene visualizzato sempre i gruppi in ordine e, per ogni gruppo, sempre visualizzare le informazioni sui singoli siti Web in base agli URL visualizzati nell'elenco di URL.

Tuttavia, non è possibile prevedere l'ordine in cui i download in realtà si verificano.Dopo avere più gruppi sono stati avviati, le attività di download che generano sono qualsiasi attivo.Non è possibile presupporre che il A-1 verranno scaricati prima di B-1 e non è possibile presupporre che il A-1 verranno scaricati prima di A-2.

JJ651641.collapse_all(it-it,VS.110).gifDefinizioni globali

Il codice di esempio contiene le due dichiarazioni globali che vengono visualizzate per tutti i metodi.

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 variabile di Task, pendingWork, supervisiona il processo visualizzato e impedisce a qualsiasi gruppo di interrompere l'operazione di visualizzazione di un altro gruppo.La variabile del carattere, group, etichette l'output dei gruppi diversi per verificare che i risultati siano visualizzate in ordine previsto.

JJ651641.collapse_all(it-it,VS.110).gifIl gestore eventi Click

Il gestore eventi, StartButton_Click, incrementa la lettera del gruppo quando l'utente sceglie il pulsante Avvio.Il gestore chiama AccessTheWebAsync per eseguire l'operazione di download.

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(it-it,VS.110).gifIl metodo di AccessTheWebAsync

In questo esempio AccessTheWebAsync divisa in due metodi.Il primo metodo, AccessTheWebAsync, avvia tutte le attività di download per un gruppo e configura pendingWork per controllare visualizzare il processo.Il metodo utilizza una query (language integrated query LINQ) e ToArray<TSource> per avviare il download di attività contemporaneamente.

AccessTheWebAsync chiama quindi FinishOneGroupAsync per attendere il completamento di ogni download e visualizzare la relativa lunghezza.

FinishOneGroupAsync restituisce un'attività assegnata a pendingWork in AccessTheWebAsync.Che il valore impedisce l'interruzione da un'altra operazione prima che l'attività venga completata.

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(it-it,VS.110).gifIl metodo di FinishOneGroupAsync

Questo metodo cicla con le attività di download in un gruppo, ciascuno in attesa, restituisce la lunghezza del sito Web scaricato e aggiungendo la lunghezza a totale.

La prima istruzione in FinishOneGroupAsync utilizza pendingWork per assicurarsi che fornisce il metodo non interferire con un'operazione nel processo visualizzato o già in attesa.Se tale operazione è in corso, l'operazione immettendo deve attendere il proprio 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);
}

È possibile eseguire l'esempio incollando le modifiche nel codice in Compilare l'applicazioneo, è possibile seguire le istruzioni in Scaricare l'applicazione scaricare l'esempio quindi eseguire il progetto QueueResults.

JJ651641.collapse_all(it-it,VS.110).gifPunti di interesse

Le righe di informazioni che iniziano con un segno di cancelletto (#) nell'output illustrano come questo esempio è.

L'output indica i seguenti modelli.

  • Un gruppo può essere avviato come un gruppo precedente visualizzare il relativo output, ma la visualizzazione dell'output del gruppo precedente non viene interrotta.

    #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
    
  • L'attività di pendingWork è null (Nothing in Visual Basic) all'inizio di FinishOneGroupAsync solo per il gruppo A, che ha avviato per primo.Raggruppare A non ha ancora completato un'espressione di attesa quando raggiunge FinishOneGroupAsync.Di conseguenza, il controllo non ha restituito a AccessTheWebAsynce la prima assegnazione a pendingWork non si è verificata.

  • Le due righe vengono sempre visualizzati insieme nell'output.Il codice non viene interrotto mai tra avviare l'operazione di un gruppo in StartButton_Click e assegnare un'attività per il gruppo a pendingWork.

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

    Dopo che un gruppo immette StartButton_Click, l'operazione non completa un'espressione di attendere che l'operazione non immettere FinishOneGroupAsync.Di conseguenza, nessun'altra operazione può guadagnare il controllo durante quel segmento di codice.

Rivisto ed eseguendo l'applicazione di esempio

Per comprendere meglio l'applicazione di esempio, è possibile scaricarlo, essere compilato manualmente, o esaminare il codice alla fine di questo argomento senza distribuire l'applicazione.

[!NOTA]

Per eseguire l'esempio come applicazione desktop di Windows Presentation Foundation (WPF), è necessario disporre di Visual Studio 2012 Visual Studio express 2012 per Windows Desktop, o .NET Framework 4,5 installato nel computer.

Per eseguire l'esempio come applicazione di Windows Store, è necessario disporre di Windows 8 installato nel computer.Inoltre, se si desidera eseguire l'esempio da Visual Studio, è necessario disporre di Visual Studio 2012 o Visual Studio express 2012 per Windows 8 installato.In Visual Studio 2010 non è possibile caricare i progetti che vengono destinati a .NET Framework 4,5.

JJ651641.collapse_all(it-it,VS.110).gifScaricare l'applicazione

  1. Scaricare il file appiattito da Esempi di Async: Reentrancy nelle applicazioni desktop .NET o Esempi di Async: Reentrancy nelle applicazioni di archivio di Windows.

  2. Decomprimere il file che viene scaricato e quindi avviare Visual Studio.

  3. Sulla barra dei menu scegliere File, Apri, Progetto/Soluzione.

  4. Passare alla cartella che contiene il codice di esempio decompresso quindi aprire il file di soluzione (sln).

  5. In Esplora soluzioni, scegliere dal menu di scelta rapida del progetto che si desidera eseguire e scegliere Imposta come StartUpProject.

  6. Scegliere i tasti CTRL+F5 per compilare ed eseguire il progetto.

JJ651641.collapse_all(it-it,VS.110).gifCompilare l'applicazione

Nelle sezioni seguenti vengono fornite il codice per compilare l'esempio come applicazione WPF o come applicazione di Windows Store.

Per compilare un'applicazione WPF

  1. Avviare Visual Studio 2012.

  2. Nella barra del menu, scegliere File, Nuovo, Progetto.

    Verrà visualizzata la finestra di dialogo Nuovo progetto.

  3. Nel riquadro Modelli installati, espandere Visual Basic o **Visual C#**quindi espandere Finestre.

  4. Nell'elenco di tipi di progetto, scegliere Applicazione WPF.

  5. Denominare il progetto WebsiteDownloadWPFquindi scegliere il pulsante OK.

    Il nuovo progetto verrà visualizzato in Esplora soluzioni.

  6. Nell'editor di codice di Visual Studio, scegliere la scheda MainWindow.xaml.

    Se la scheda non è visibile, scegliere dal menu di scelta rapida per MainWindow.xaml in Esplora soluzioniquindi scegliere Visualizza codice.

  7. Nel visualizzazione XAML di MainWindow.xaml, sostituire il codice con il seguente.

    <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 semplice finestra che contiene una casella di testo e un pulsante vengono visualizzati nella visualizzazione Progettazione di MainWindow.xaml.

  8. Aggiungere un riferimento per System.Net.Http.

  9. In Esplora soluzioni, aprire il menu di scelta rapida per MainWindow.xaml.vb o MainWindow.xaml.cs e scegliere Visualizza Codice.

  10. In MainWindow.xaml.vb o MainWindow.xaml.cs sostituire il codice con il seguente.

    ' 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. Scegliere i tasti CTRL+F5 per eseguire il programma e quindi scegliere il pulsante Avvio più volte.

  12. Apportare le modifiche da Disabilitare il pulsante Start, da Riavviare e annullare l'operazione, o da Eseguire più operazioni e mettere in coda di output per gestire il motivo.

Per compilare le finestre dell'applicazione

  1. Avviare Visual Studio 2012.

  2. Nella barra del menu, scegliere File, Nuovo, Progetto.

    Verrà visualizzata la finestra di dialogo Nuovo progetto.

  3. In Installato, la categoria Modelli, espandere Visual Basic o **Visual C#**quindi espandere Windows Store.

  4. Nell'elenco di tipi di progetto, scegliere Applicazione vuota (XAML).

  5. Denominare il progetto WebsiteDownloadWinquindi scegliere il pulsante OK.

    Il nuovo progetto verrà visualizzato in Esplora soluzioni.

  6. In Esplora soluzioni, scegliere dal menu di scelta rapida per MainPage.xaml quindi scegliere Apri.

  7. Nella finestra XAML del file MainPage.xaml, sostituire il codice con il codice seguente.

    <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 finestra semplice che contiene una casella di testo e un pulsante Avvio viene visualizzato nella finestra Progettazione del file MainPage.xaml.

  8. In Esplora soluzioni, scegliere dal menu di scelta rapida per MainPage.xaml.vb o MainPage.xaml.cs quindi scegliere Visualizza codice.

  9. Sostituire il codice in MainPage.xaml.vb o in MainPage.xaml.cs con il codice seguente.

    ' 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. Scegliere i tasti CTRL+F5 per eseguire il programma e quindi scegliere il pulsante Avvio più volte.

  11. Apportare le modifiche da Disabilitare il pulsante Start, da Riavviare e annullare l'operazione, o da Eseguire più operazioni e mettere in coda di output per gestire il motivo.

Vedere anche

Attività

Procedura dettagliata: accesso al Web tramite Async e Await (C# e Visual Basic)

Concetti

Programmazione asincrona con Async e Await (C# e Visual Basic)

Altre risorse

Programmazione asincrona (finestre archiviano le applicazioni)

Guida rapida: API asincroni chiamante in c o in Visual Basic