Freigeben über


Ablauf des erneuten Eintretens in asynchronen Anwendungen (C# und Visual Basic)

Wenn Sie asynchronen Code in der Anwendung einschließen, sollten Sie Reentranz berücksichtigen und möglicherweise verhindern, die erneute eingeben asynchroner Operationen verweist, bevor sie abgeschlossen ist.Wenn Sie Möglichkeiten für Reentranz identifizieren und nicht behandeln kann, kann dies zu unerwarteten Ergebnissen führen.

In diesem Thema

HinweisHinweis

Die Anweisungen in Überprüfung und die Beispiels-App Ausführen zeigen, wie Sie den Code entweder als App (Windows Presentation Foundation) oder als Windows Store-App ausführt.

Um das Beispiel als WPF-App auszuführen, müssen Sie Visual Studio 2012, Visual Studio Express 2012 für Windows Desktop oder .NET Framework 4.5 enthalten, das auf dem Computer installiert ist.

Um das Beispiel als Windows Store-App auszuführen, müssen Sie Windows 8 enthalten, das auf dem Computer installiert ist.Wenn Sie das Beispiel aus Visual Studio ausführen möchten, müssen Sie Visual Studio 2012 auch oder Visual Studio Express 2012 für Windows 8 installiert.

Erkennung von Reentranz

Im Beispiel in diesem Thema, um Benutzer eine Schaltfläche Start, um eine asynchrone App zu initiieren, die eine Reihe von Websites Herunterladen und leiten die Gesamtanzahl von Bytes, die heruntergeladen werden.Eine synchrone Version des Beispiels würde dieselbe Methode reagieren unabhängig davon, wieoft ein Benutzer die Schaltfläche auswählt, da, nachdem das erste Mal, der UI-Thread diese Ereignisse ignoriert, bis die Anwendung beendet ausgeführt werden.In einer asynchronen App jedoch wird der UI-Thread fort, um zu reagieren, und Sie können möglicherweise den asynchronen Vorgangs erneut bevor er abgeschlossen ist.

Im folgenden Beispiel wird die erwartete Ausgabe angezeigt, wenn der Benutzer die Schaltfläche Start nur einmal auswählt.Eine Liste der heruntergeladenen Websites wird mit der Größe, in Bytes, jeder Site.Die Gesamtanzahl der Bytes wird am Ende.

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

Wenn der Benutzer die Schaltfläche mehrmals auswählt, wird der Ereignishandler wiederholt aufgerufen, und der Herunterladen wird jedes Mal erneut eingegeben.Daher werden mehrere asynchrone Vorgänge gleichzeitig, die Ausgabeüberlappen die Ergebnisse, und die Gesamtzahl der Bytes ist verwirrend.

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

Sie können den Code überprüfen, der diese Ausgabe erzeugt, indem am Ende dieses Themas durch.Sie können mit dem Code experimentieren, indem Sie die Projektmappe auf dem lokalen Computer herunterladen und das WebsiteDownload-Projekt oder, indem Sie den Code am Ende dieses Themas dann, das Ausführen von verwenden, um ein eigenes Projekt weitere Informationen und Anweisungen zu erstellen, finden Sie unter Überprüfung und die Beispiels-App Ausführen.

Behandlungs-Reentranz

Sie können behandeln Reentranz in einer Vielzahl von Methoden, je nachdem, was Sie die Anwendung ausführen möchten.In diesem Thema wird die folgenden Beispiele vor:

JJ651641.collapse_all(de-de,VS.110).gifDeaktivieren Sie den Schaltfläche Start

Sie können die Schaltfläche Start blockieren, während ein Vorgang ausgeführt wird, indem die Schaltfläche oben im StartButton_Click-Ereignishandlers deaktiviert.Sie können die Schaltfläche aus einem finally-Block erneut aktivieren wenn die Beenden, damit Benutzer die Anwendung erneut ausführen können.

Im folgenden Code wird diese Änderungen an, die mit Sternchen gekennzeichnet werden.Sie können Änderungen am Code am Ende dieses Themas hinzufügen, oder Sie können die fertige App von Asynchrone Beispiele: Reentranz in .NET-Desktop-Apps herunterladen oder Asynchrone Beispiele: Reentranz in Windows Store-Apps.Der Projektname ist 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;
    }
}

Aufgrund der Änderungen reagiert die Schaltfläche nicht, während AccessTheWebAsync die Websites herunterladen, sodass der Prozess nicht erneut eingegeben werden.

JJ651641.collapse_all(de-de,VS.110).gifAbbrechen und starten den Vorgang neu

Anstatt, die Schaltfläche Start zu deaktivieren, können Sie die Schaltfläche aktiv bleiben jedoch, wenn der Benutzer diese Schaltfläche erneut auswählt, brechen den Vorgang ab, der bereits ausgeführt wird und den zuletzt begonnenen Vorgang fortgesetzt werden soll.

Weitere Informationen zum Abbruch, finden Sie unter Abstimmen der asynchronen Anwendung.

Um dieses Szenario zu installieren, nehmen Sie die folgenden Änderungen am Grundlegender Code vor der in Überprüfung und die Beispiels-App Ausführen bereitgestellt wird.Sie können die fertige App von Asynchrone Beispiele: Reentranz in .NET-Desktop-Apps herunterladen oder Asynchrone Beispiele: Reentranz in Windows Store-Apps.Der Name dieses Projekts ist CancelAndRestart.

  1. Deklarieren Sie eine Variable CancellationTokenSource, cts, die im Bereich für alle Methoden ist.

    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 bestimmen Sie, ob ein Vorgang bereits ausgeführt wird.Wenn der Wert von ctsNothing (in Visual Basic) NULL ist, ist kein Vorgang bereits aktiv.Wenn der Wert nicht NULL ist, wird der Vorgang, der bereits ausgeführt wird, abgebrochen.

    ' *** 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. Legen Sie cts in einen anderen Wert fest, der den aktuellen Prozess darstellt.

    ' *** 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. Am Ende der StartButton_Click, ist der aktuelle Prozess abgeschlossen, sodass legen Sie den Wert für cts zurück auf NULL fest.

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

Der folgende Code zeigt alle Änderungen in StartButton_Click an.Die Ergänzungen werden mit Sternchen gekennzeichnet.

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 nehmen Sie die folgenden Änderungen vor.

  • Fügen Sie einen Parameter hinzu, um das Abbruchtoken von StartButton_Click zu akzeptieren.

  • Verwenden Sie die GetAsync-Methode, um die Websites herunterzuladen, da GetAsyncCancellationToken ein Argument akzeptiert.

  • Bevor Sie DisplayResults aufrufen, um die Ergebnisse für jede Website heruntergeladene anzuzeigen, aktivieren Sie ct, um sicherzustellen, dass der aktuelle Vorgang nicht abgebrochen wurde.

Im folgenden Code wird diese Änderungen an, die mit Sternchen gekennzeichnet werden.

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

Wenn Sie die Schaltfläche Start mehrmals auswählen, während diese App ausgeführt wird, sollte sie Ergebnisse erzeugen, die der folgenden Ausgabe ähneln.

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

Um die Teilausführungslisten auszuschließen, markieren Sie die erste Codezeile in StartButton_Click Auskommentierung um das Textfeld zu löschen jedes Mal bei der Benutzer den Vorgang neu gestartet.

JJ651641.collapse_all(de-de,VS.110).gifFühren Sie mehrere Vorgänge aus und erstellen Sie die Ausgabe in die Warteschlange

Dieses dritte ist ein Beispiel für das schwierigste, dass die Anwendung einen anderen asynchronen Vorgang jedes Mal, wenn der Benutzer die Schaltfläche Start auswählt und alle Vorgänge, die vollständig ausgeführt werden beginnt.Alle angeforderten Vorgänge laden Websites aus der Liste asynchron herunter, aber die Ausgabe der Vorgänge wird sequenziell dargestellt.Das heißt, wird die tatsächliche Downloadingaktivität überlappen, da die Ausgabe in Erkennung von Reentranz Zeigt, aber die Ergebnisliste für jede Gruppe getrennt angezeigt wird.

Die Vorgänge geben globales Task, pendingWork frei, das als Gatekeeper für den Anzeigenprozess dient.

Sie können dieses Beispiel ausführen, indem Sie die Änderungen in den Code in Erstellen der App einfügen, oder Sie können die Anweisungen in Herunterladen der App entsprechen, das Beispiel herunterzuladen und das QueueResults-Projekt dann auszuführen.

Die folgende Ausgabe zeigt das Ergebnis, wenn der Benutzer die Schaltfläche Start nur einmal auswählt.Die Buchstabenbezeichnung, A, gibt an, dass das Ergebnis zum ersten Mal von der Schaltfläche Start ausgewählt ist.Die Zahlen zeigen die Reihenfolge der URL in der Liste der Downloadzielen an.

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

Wenn der Benutzer die Schaltfläche Start dreimal auswählt, erzeugt die App Ausgabe, die den folgenden Zeilen ähnelt.Die Informationszeilen, die einer Ablaufverfolgung des Nummernzeichens (#) den Status der Anwendung starten.

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

Anfang der Gruppen B und C, bevor Gruppe A beendet, aber die Ausgabe für die jede Gruppe getrennt wird.Die gesamte Ausgabe für Gruppe A wird zuerst, gefolgt von der gesamte Ausgabe für Gruppe B und anschließend von aller Ausgabe für Gruppe C.Die Anwendung zeigt immer die Gruppen in der Reihenfolge und, für jede Gruppe an, zeigt immer die Informationen über die einzelnen Websites in der Reihenfolge an, dass die URL in der Liste von URLs angezeigt wird.

Sie können jedoch die Reihenfolge nicht vorhersagen, in der die Downloads tatsächlich vorkommen.Nachdem mehrere Gruppen gestartet wurden, aktive alle sind Downloadaufgaben, die sie generieren.Sie können nicht davon ausgehen, dass A-1 vor B-1 heruntergeladen wird, und Sie können nicht davon ausgehen, dass A-1 vor A-2 heruntergeladen wird.

JJ651641.collapse_all(de-de,VS.110).gifGlobale Definitionen

Der Beispielcode enthält die folgenden zwei globalen Deklarationen, die von allen Methoden sichtbar sind.

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

Die Task-Variable, pendingWork, beaufsichtigt den Anzeigenprozess und verhindert eine Gruppe an der Unterbrechung des Anzeigenvorgangs einer anderen Gruppe.Die Zeichenvariable, group, die die Ausgabe von unterschiedlichen Gruppen, um sicherzustellen, dass Ergebnisse in der erwarteten Reihenfolge angezeigt werden.

JJ651641.collapse_all(de-de,VS.110).gifDer Click-Ereignishandler

Der Ereignishandler, StartButton_Click, erhöht der Gruppenbuchstabe jedes Mal, wenn der Benutzer die Schaltfläche Start auswählt.Anschließend ruft der Handler AccessTheWebAsync auf, um den Downloadingvorgang auszuführen.

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(de-de,VS.110).gifDie AccessTheWebAsync-Methode

In diesem Beispiel wird AccessTheWebAsync in zwei Methoden.Die erste Methode, AccessTheWebAsync, beginnen alle Downloadaufgaben für eine Gruppe und richtet pendingWork, den Anzeigenprozess zu steuern.Die - Methode verwendet (Language-Integrated Query LINQ-Abfrage) und ToArray<TSource>, um des gesamten Downloads zu starten weist gleichzeitig eine Arbeit zu.

AccessTheWebAsyncFinishOneGroupAsync ruft dann auf, um den Abschluss jeder einzelnen Downloads zu erwarten und die Länge anzuzeigen.

FinishOneGroupAsync gibt eine Aufgabe zurück, pendingWork in AccessTheWebAsync die zugewiesen wird.Dieser Wert Unterbrechung durch einen anderen Vorgang verhindert wird, bevor die Aufgabe abgeschlossen wurde.

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(de-de,VS.110).gifDie FinishOneGroupAsync-Methode

Diese Methode wird über die Downloadaufgaben in einer Gruppe diese, erwartet jedes an, wird die Länge der heruntergeladenen Website, und fügt die Länge zur Summe hinzu.

Die erste Anweisung in FinishOneGroupAsync verwendet pendingWork, ob beim Eingeben der Methode zu überprüfen, keinen Vorgang behindert, der bereits im Anzeigenprozess ist, oder der bereits wartet.Wenn ein solcher Vorgang ausgeführt wird, muss der eingebende Vorgang die Drehung warten.

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

Sie können dieses Beispiel ausführen, indem Sie die Änderungen in den Code in Erstellen der App einfügen, oder Sie können die Anweisungen in Herunterladen der App entsprechen, das Beispiel herunterzuladen, und das QueueResults-Projekt dann auszuführen.

JJ651641.collapse_all(de-de,VS.110).gifSehenswürdigkeiten

Die Informationszeilen, die mit einem Nummernzeichen (#) in der Ausgabe beginnen, erläutert wird, wie dieses Beispiel funktioniert.

Die Ausgabe zeigt die folgenden Muster.

  • Eine Gruppe kann gestartet werden, während eine vorherige Gruppe die Ausgabe angezeigt wird, aber die Anzeige der vorherigen Ausgabe der Gruppe nicht unterbrochen wird.

    #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
    
  • Die pendingWork Aufgabe ist Nothing (in Visual Basic) am Anfang FinishOneGroupAsync nur für eine Gruppe NULL, die zuerst gestartet wurde.Gruppieren Sie eine noch nicht abgeschlossen einen Erwartungsausdruck, wenn es FinishOneGroupAsync erreicht.Daher ist Steuerelement nicht an AccessTheWebAsync zurückgegeben, und die erste Zuweisung zu pendingWork ist nicht aufgetreten.

  • Die folgenden zwei Zeilen werden immer zusammen in der Ausgabe.Der Code wird nie zwischen dem Starten des Vorgangs einer Gruppe in StartButton_Click und Rollenzuweisung pendingWork einer Aufgabe für die Gruppe unterbrochen.

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

    Nachdem eine Gruppe StartButton_Click eingibt, wird der Vorgang erst Erwartungsausdruck ab, bis der Vorgang FinishOneGroupAsync eingibt.Daher kann kein weiterer Vorgang Steuerelement während dieses Abschnitts des Codes erhalten.

Überprüfung und die Beispiels-App Ausführen

Um die Beispiels-App besser zu verstehen, können Sie sie herunterladen, sie selbst erstellen oder den Code am Ende dieses Themas überprüfen ohne die Anwendung zu implementieren.

HinweisHinweis

Um das Beispiel als Desktop-App WPF (Windows Presentation Foundation) auszuführen, müssen Sie Visual Studio 2012, Visual Studio Express 2012 für Windows Desktop oder .NET Framework 4.5 enthalten, das auf dem Computer installiert ist.

Um das Beispiel als Windows Store-App auszuführen, müssen Sie Windows 8 enthalten, das auf dem Computer installiert ist.Wenn Sie das Beispiel aus Visual Studio ausführen möchten, müssen Sie Visual Studio 2012 auch oder Visual Studio Express 2012 für Windows 8 installiert.Visual Studio 2010 kann Projekte nicht laden, die für .NET Framework 4.5 verwendet werden.

JJ651641.collapse_all(de-de,VS.110).gifHerunterladen der App

  1. Laden Sie die komprimierte Datei von Asynchrone Beispiele: Reentranz in .NET-Desktop-Apps herunter oder Asynchrone Beispiele: Reentranz in Windows Store-Apps.

  2. Dekomprimieren Sie die Datei, die Sie heruntergeladen haben, und starten Sie dann Visual Studio.

  3. Klicken Sie in der Menüleiste auf Datei, dann auf Öffnen und Projekt/Projektmappe.

  4. Navigieren Sie zum Ordner, der den dekomprimierten Beispielcode enthält, und öffnen Sie die Projektmappendatei (.sln).

  5. In Projektmappen-Explorer öffnen Sie das Kontextmenü für das Projekt, das Sie ausführen möchten, und wählen Sie dann Als Startprojekt festlegen aus.

  6. Wählen Sie die STRG+F5-Tasten, um das Projekt zu erstellen und auszuführen.

JJ651641.collapse_all(de-de,VS.110).gifErstellen der App

Die folgenden Abschnitte enthalten den Code, um das Beispiel als WPF-App oder als Windows Store-App zu erstellen.

So fügen Sie eine WPF-App erstellen

  1. Starten Sie Visual Studio 2012.

  2. Wählen Sie in der Menüleiste Datei, Neu, Projekt aus.

    Das Dialogfeld Neues Projekt wird angezeigt.

  3. Im Bereich Installierte Vorlagen erweitern Sie Visual Basic oder Visual C#, und erweitern Sie dann Fenster.

  4. In der Liste der - Projekttypen, wählen Sie WPF-Anwendung aus.

  5. Nennen Sie das Projekt WebsiteDownloadWPF, und wählen Sie dann die Schaltfläche OK aus.

    Das neue Projekt wird im Projektmappen-Explorer angezeigt.

  6. In Visual Studio MainWindow.xaml wählen Sie die Registerkarte aus.

    Wenn die Registerkarte nicht sichtbar ist, öffnen Sie das Kontextmenü für MainWindow.xaml in Projektmappen-Explorer, und wählen Sie dann Code anzeigen aus.

  7. In der Ansicht XAML der Datei MainWindow.xaml, ersetzen Sie den Code durch den folgenden Code.

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

    Ein einfaches Fenster, das ein Textfeld und eine Schaltfläche enthält, wird in der Ansicht Entwurf der Datei MainWindow.xaml.

  8. Fügen Sie einen Verweis für System.Net.Http hinzu.

  9. In Projektmappen-Explorer öffnen Sie das Kontextmenü für MainWindow.xaml.cs oder MainWindow.xaml.vb, und wählen Sie dann Code anzeigen aus.

  10. Klicken Sie in "MainWindow.xaml.vb" oder ersetzen Sie den Code durch den folgenden Code.

    ' 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. Wählen Sie die STRG+F5-Tasten, um das Programm auszuführen, und wählen Sie dann die Schaltfläche Start mehrmals aus.

  12. Nehmen Sie die Änderungen von Deaktivieren Sie den Schaltfläche Start, von Abbrechen und starten den Vorgang neu oder von Führen Sie mehrere Vorgänge aus und erstellen Sie die Ausgabe in die Warteschlange vor, um die Reentranz zu behandeln.

So fügen Sie Windows Store-App erstellen

  1. Starten Sie Visual Studio 2012.

  2. Wählen Sie in der Menüleiste Datei, Neu, Projekt aus.

    Das Dialogfeld Neues Projekt wird angezeigt.

  3. In Installiert erweitern Kategorie Vorlagen, Visual Basic oder Visual C# und erweitern Sie dann Windows Store.

  4. In der Liste der - Projekttypen, wählen Sie Leere App (XAML) aus.

  5. Nennen Sie das Projekt WebsiteDownloadWin, und wählen Sie dann die Schaltfläche OK aus.

    Das neue Projekt wird im Projektmappen-Explorer angezeigt.

  6. In Projektmappen-Explorer öffnen Sie das Kontextmenü für "MainPage.xaml", und wählen Sie dann Öffnen aus.

  7. Im Fenster XAML von "MainPage.xaml", ersetzen Sie den Code durch den folgenden Code.

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

    Ein einfaches Fenster, das ein Textfeld und eine Schaltfläche Start enthält, wird im Fenster Entwurf von " MainPage.xaml ".

  8. In Projektmappen-Explorer öffnen Sie das Kontextmenü für MainPage.xaml.vb oder MainPage.xaml.cs, und wählen Sie dann Code anzeigen aus.

  9. Ersetzen Sie den Code in MainPage.xaml.vb oder in MainPage.xaml.cs durch den folgenden Code.

    ' 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. Wählen Sie die STRG+F5-Tasten, um das Programm auszuführen, und wählen Sie dann die Schaltfläche Start mehrmals aus.

  11. Nehmen Sie die Änderungen von Deaktivieren Sie den Schaltfläche Start, von Abbrechen und starten den Vorgang neu oder von Führen Sie mehrere Vorgänge aus und erstellen Sie die Ausgabe in die Warteschlange vor, um die Reentranz zu behandeln.

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Zugreifen auf das Web mit Async und Await (C# und Visual Basic)

Konzepte

Asynchrone Programmierung mit Async und Await (C# und Visual Basic)

Weitere Ressourcen

Asynchrone Programmierung (Windows Store-Apps)

Schnellstart: Aufrufen von asynchrones APIs in C# oder in Visual Basic