WhenAny: łączenie platformy .NET Framework ze środowiskiem wykonawczym systemu Windows (C# i Visual Basic)

Przykład w tym temacie łączy typ Środowisko wykonawcze systemu Windows , który pobiera kanały bloga asynchronicznie za pomocą metody .NET Framework, która przetwarza zadania asynchroniczne w kolejności ich wykonania.Aby uzyskać więcej informacji na temat tego typu, zobacz SyndicationClient.Aby uzyskać więcej informacji, na temat metody, zobacz Task.WhenAny.

Łącząc te funkcje, można rozpocząć jednocześnie pobieranie wielu źródeł informacji blog i przetwarzanie wyników po ich zakończeniu.Jeśli jedno źródło danych jest pobierane szybciej niż pozostałe, jego wyniki są wyświetlane jako pierwsze.Za pomocą SyndicationClient metody, można pobrać źródła danych łatwiej; za pomocą Task.WhenAny metody, można łatwiej zidentyfikować następne źródła danych, które zakończyły pobieranie.

[!UWAGA]

Aby uruchomić przykład, musisz mieć zainstalowany na komputerze Windows 8.Ponadto, jeśli użytkownik chce uruchomić przykład z programu Visual Studio, musi także posiadać zainstalowane Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 for Windows 8 lub Visual Studio Express 2013 for Windows.

Poniższy kod łączy te funkcje z Środowisko wykonawcze systemu Windows i .NET Framework:

Try 
    Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) =
        From uri In uriList
        Select client.RetrieveFeedAsync(uri).AsTask()
    ' AsTask changes the returns from RetrieveFeedAsync into tasks. 

    ' Run the query to start all the asynchronous processes. 
    Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList()

    Dim feed As SyndicationFeed

    ' Repeat the following until there are no tasks left: 
    '    - Grab the first one that finishes. 
    '    - Retrieve the results from the task (what the return statement  
    '      in RetrieveFeedAsync returns). 
    '    - Remove the task from the list. 
    '    - Display the results. 
    While blogFeedTasksList.Count > 0
        Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
        feed = Await nextTask
        blogFeedTasksList.Remove(nextTask)
        DisplayResults(feed)
    End While 

Catch ex As Exception
    ResultsTextBox.Text =
        "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
End Try
try
{
    IEnumerable<Task<SyndicationFeed>> feedsQuery =
            from uri in uriList
            // AsTask changes the returns from RetrieveFeedAsync into tasks. 
            select client.RetrieveFeedAsync(uri).AsTask();

    // Run the query to start all the asynchronous processes.
    List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList();

    SyndicationFeed feed;

    // Repeat the following until no tasks remain: 
    //    - Grab the first one that finishes. 
    //    - Retrieve the results from the task (what the return statement  
    //      in RetrieveFeedAsync returns). 
    //    - Remove the task from the list. 
    //    - Display the results. 
    while (blogFeedTasksList.Count > 0)
    {
        Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
        feed = await nextTask;                    
        blogFeedTasksList.Remove(nextTask);
        DisplayResults(feed);
    }
}
catch (Exception ex)
{
    ResultsTextBox.Text =
        "Page could not be loaded.\n\r" + "Exception: " + ex.ToString();
}

Przykład generuje dane wyjściowe podobne do następujących wierszy:Dla każdego bloga wyświetlacz pokazuje tytuł bloga, a także tytuły i daty postów na blogu.

Developing for Windows
     New blog for Windows 8 app developers, 5/1/2012 2:33:02 PM -07:00
     Trigger-Start Services Recipe, 3/24/2011 2:23:01 PM -07:00
     . . .
     Countdown to PDC10, 10/26/2010 4:11:28 PM -07:00

Extreme Windows Blog
     PDXLAN 20: “Epidemic” Custom PC by Jon Hansz, 7/30/2012 2:31:35 PM -07:00
     Samsung Notebook Series 9: Taking Thin and Light to the Extreme, 7/23/2012 12:06:03 PM -07:00
     . . .
     AMD Unveils A-Series APUs, 6/13/2011 9:34:01 PM -07:00

Blogging Windows
     Windows 8 has reached the RTM milestone, 8/1/2012 9:00:00 AM -07:00
     Windows 8 will be available on…, 7/18/2012 1:09:00 PM -07:00
     . . .
     More buzz from BUILD – Developers get their devices!, 9/13/2011 7:47:57 PM -07:00

Springboard Series Blog
     What to Expect in User Experience Virtualization Beta 2, 6/25/2012 11:03:27 PM -07:00
     Introducing Microsoft BitLocker Administration 2.0 Beta, 6/12/2012 8:08:23 AM -07:00
     . . .
     The Springboard Series Visits Lima, Peru, 11/18/2011 5:27:37 AM -08:00

Pozostała część tego tematu zawiera szczegóły dotyczące tworzenia przykładu i jego funkcjonowania.

Aby móc uruchomić tę aplikację, trzeba mieć zainstalowane na komputerze Visual Studio 2012 oraz Windows 8.

Ten temat zawiera następujące sekcje.

  • Opcje instalacji dla przykładu
  • Ogólne informacje Kod startowy
  • Rozszerzanie kodu startowego
  • Pobieranie kodu startowego
  • Pobieranie gotowych aplikacji
  • Kompilowanie kodu startowego
  • Kompilowanie gotowych aplikacji
  • Tematy pokrewne

Opcje instalacji dla przykładu

Przykład jest oparty na czytniku blogów opisanym w Szybki Start: używanie operatora "await" dla programowania asynchronicznego.Jednak kod startowy dla tego tematu pobiera wiele źródeł danych blogów zamiast jednego.

Kod startowy używa funkcji Środowisko wykonawcze systemu Windows, aby pobierać kanały blogów sekwencyjnie.Oznacza to, że źródła danych z blogów są pobierane w kolejności, w której są wyświetlane w zbiorze adresów URL.Gotowa aplikacja dodaje funkcje z .NET Framework do pobrania danych z kanału bloga w kolejności zakończania.

Możesz skonfigurować kod przykładowy na jeden z poniższych sposobów:

  • Kod startowy.

    • Możesz pobrać kod początkowy samodzielnie wypełniając instrukcje w Pobieranie kodu początkowego,

    • Możesz tworzyć kod początkowy samodzielnie wypełniając instrukcje w Kompilowanie kodu początkowego.

    • Możesz ocenić kod początkowy bez jego implementacji przez przewinięcie do Kompilowanie kodu początkowego.

  • Zakończona aplikacja.

    • Możesz pobierać ukończone aplikacje wypełniając instrukcje w Pobieranie ukończonej aplikacji

    • Możesz samodzielnie skompilować aplikacje wypełniając instrukcje w Kompilowanie ukończonej aplikacji.

    • Możesz ocenić ukończoną aplikację bez jej implementacji przez przewinięcie do Kompilowanie ukończonej aplikacji.

Rozdział Zrozumieć kod początkowy omawia kluczowe zagadnienia w rozwiązaniu podstawowym.

Sekcja Rozszerzanie kodu startowego przedstawia sposób modyfikowania kodu przez dodanie AsTask``2 i Task.WhenAny.

Ogólne informacje Kod startowy

Kod startowy używa metody SyndicationClient, RetrieveFeedAsync, aby pobierać kanał bloga z każdego URI na liście URI.Każde wywołanie metody zwraca IAsyncOperationWithProgress wystąpienia, która reprezentuje trwającą operację asynchroniczną.Kiedy oczekiwana, operacja asynchroniczna wytwarza wystąpienie SyndicationFeed, które zawiera informacje o pobranym kanale bloga.

Kod określa zapytanie, które odnosi się RetrieveFeedAsync do każdego wpisu na liście identyfikatorów URI.Przy wykonaniu, zapytanie zwraca kolekcję wystąpień IAsyncOperationWithProgress.

Dim feedsQuery As IEnumerable(Of IAsyncOperationWithProgress(Of SyndicationFeed, 
                                                                RetrievalProgress)) =
                                                From uri In uriList
                                                Select client.RetrieveFeedAsync(uri)
IEnumerable<IAsyncOperationWithProgress<SyndicationFeed, 
    RetrievalProgress>> feedsQuery = from uri in uriList
                                     select client.RetrieveFeedAsync(uri);

ToList``1 wykonuje kwerendę i rozpoczyna proces asynchroniczny, co ilustruje poniższy kod.

Dim blogFeedOpsList As List(Of IAsyncOperationWithProgress(Of SyndicationFeed, 
                                                           RetrievalProgress)) =
                                               feedsQuery.ToList()
List<IAsyncOperationWithProgress<SyndicationFeed, 
    RetrievalProgress>> blogFeedOpsList = feedsQuery.ToList();

W tym momencie użytkownik ma listy aktywnych IAsyncOperationWithProgress wystąpień.Nadal należy czekać na każde wystąpienie, aby otrzymać ostateczne wyniki.

Następująca pętla czeka na każde wystąpienie IAsyncOperationWithProgress w celu pobrania wyników SyndicationFeed.

Dim feed As SyndicationFeed
For Each blogFeedOp In blogFeedOpsList
    ' The Await operator retrieves the final result (a SyndicationFeed instance) 
    ' from each IAsyncOperation instance.
    feed = Await blogFeedOp
    DisplayResults(feed)
Next
SyndicationFeed feed;
foreach (var blogFeedOp in blogFeedOpsList)
{
    // The await operator retrieves the final result (a SyndicationFeed instance) 
    // from each IAsyncOperation instance.
    feed = await blogFeedOp;
    DisplayResults(feed);
}

Możesz ocenić tę wersję programu w rozdziale Kompilacja kodu początkowego na końcu tematu.

Możesz naleźć więcej informacji o programowaniu z asynchronicznymi Środowisko wykonawcze systemu Windows API w Szybki start: używanie operatora await do programowania asynchronicznego.

Rozszerzanie kodu startowego

Kod startowy pokazuje, że SyndicationClient ułatwia pobieranie kanałów blogu.Krok pozostały do ukończenia przykładu to umożliwienie aplikacji przetwarzania informacji z bloga w kolejności, w której ukończone jest ich pobieranie zamiast w kolejności ich występowania na liście URI.

Kluczem do osiągnięcia poprawy jest metoda Task.WhenAny.Jeżeli zastosujesz WhenAny do kolekcji asynchronicznych procesów, metoda zwraca pierwszy proces, który ukończy, minimalizując czas oczekiwania.W tym przykładzie kolejność w jakiej są podawane informacje w blogu nie jest ważna.Jeżeli pobieranie jest wolne, najpierw mogą wyświetlić się wyniki z innego blogu.Sytuacja jest idealna w przypadku WhenAny z wyjątkiem: WhenAny wymaga kolekcji zadań.

Wywoływanie AsTask

WhenAny wymaga kolekcji wystąpień Task lub Task, ale metoda SyndicationClient która pobiera kanały blogów zwraca wystąpienie IAsyncOperationWithProgress.Tym samym, aplikacja musi stanowić pomost pomiędzy obiektami IAsyncOperationWithProgress z Środowisko wykonawcze systemu Windows oraz obiektami Task z .NET Framework.

.NET Framework oferuje AsTask``2 rozszerzone metody w celu dokonania przejścia.Kiedy wywołujesz AsTask na IAsyncOperationWithProgress wystąpieniu, AsTask zwraca zadanie, które reprezentuje operację asynchroniczną.Zadanie jest ukończone kiedy odpowiednie wystąpienie IAsyncOperationWithProgress jest ukończone i zadanie posiada wynik lub wyjątek wystąpienia.

Tym samym, wywołaj tylko AsTask dla każdego wystąpienia IAsyncOperationWithProgress , które RetrieveFeedAsync wraca, jak pokazuje poniższy kod.Kod zmienia nazwy zmiennych w celu odzwierciedlenia zmian w zadaniach i używa jawnych typowań wartości w celu przejrzystości.

Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) =
    From uri In uriList
    Select client.RetrieveFeedAsync(uri).AsTask()
' AsTask changes the returns from RetrieveFeedAsync into tasks. 

' Run the query to start all the asynchronous processes. 
Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList()
IEnumerable<Task<SyndicationFeed>> feedsQuery =
        from uri in uriList
        // AsTask changes the returns from RetrieveFeedAsync into tasks. 
        select client.RetrieveFeedAsync(uri).AsTask();

// Run the query to start all the asynchronous processes.
List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList();

[!UWAGA]

AsTask odgrywa ważną rolę w asynchronicznym programowaniu, której prawdopodobnie nie jestes świadomy.Kompilator używa AsTask razem z każdym zastosowanym operator "await" do instancji, IAsyncAction lub IAsyncOperation, co ilustruje poniższy kod.

Zastosowanie WhenAny

Ostatnim krokiem w konwersji jest dodanie metody Task.WhenAny do aplikacji.WhenAny jest zastosowany w kolekcji zadań (blogFeedTasksList) i zwraca pierwsze zadanie w kolekcji, które ukończy.Dokładniej mówiąc WhenAny zwraca zadanie zgodnie z oczekiwaniem, ocenia zadanie, które zakończyło się jako pierwsze.

Poniższa instrukcja wywołuje WhenAny i czeka na wynik.Kod wykorzystuje jawne typowanie, aby wyraźniej pokazać wynik.

Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);

Poniższy kod działa tak samo jak poprzedni, ale dzieli operację na dwie instrukcje, aby wyjaśnić, co się dzieje.Pierwsza instrukcja wywołuje WhenAny, a druga czeka na wynik.

' WhenAny returns a task that, when awaited, produces a task.
' Call:
Dim whenAnyTask As Task(Of Task(Of SyndicationFeed)) = Task.WhenAny(blogFeedTasksList)
' Await:
Dim nextTask As Task(Of SyndicationFeed) = Await whenAnyTask
// WhenAny returns a task that, when awaited, produces a task.
// Call:
Task<Task<SyndicationFeed>> whenAnyTask = Task.WhenAny(blogFeedTasksList);
// Await:
Task<SyndicationFeed> nextTask = await whenAnyTask;

Na koniec musisz zaczekać na nextTask, aby pobrać wyniki (instancja SyndicationFeed) z zadania, które zostanie ukończone jako pierwsze, a następnie usunąć nextTask z listy tak, aby nie przetwarzać go ponownie.

feed = Await nextTask
blogFeedTasksList.Remove(nextTask)
feed = await nextTask;                    
blogFeedTasksList.Remove(nextTask);

Użyj pętli tymczasowej, aby wykonać te kroki dla każdego zadania w blogFeedTasksList.

While blogFeedTasksList.Count > 0
    Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
    feed = Await nextTask
    blogFeedTasksList.Remove(nextTask)
    DisplayResults(feed)
End While
while (blogFeedTasksList.Count > 0)
{
    Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
    feed = await nextTask;                    
    blogFeedTasksList.Remove(nextTask);
    DisplayResults(feed);
}

Możesz ocenić tę wersję programu w rozdziale Kompilacja ukończonej aplikacji na końcu tematu.Lub możesz postępować zgodnie z instrukcjami w Pobieranie aplikacji zakończenia, aby wczytać projekt.

Informacje dotyczące przestrogiPrzestroga

Użycie WhenAny w pętli, jak opisano w przykładzie, jest odpowiednie w przypadku problemów zawierających małą liczbę zadań.Jednak inne podejścia są bardziej efektywne, jeśli masz dużą liczbę zadań do przetworzenia.Aby uzyskać dodatkowe informacje i obejrzeć przykłady, zobacz Przetwarzanie zadań w miarę ich ukańczania.

Pobieranie kodu startowego

Możesz pobrać kod początkowy przykładowo z Przykład async: Łączenie z .NET do Windows.Jeśli nie posiadasz dostępu do Internetu, postępuj zgodnie z instrukcjami w Kompilowanie kodu startowego na końcu tego tematu, aby utworzyć kod startowy.

Po pobraniu kodu, otwórz i uruchom go, wykonując następujące kroki.

  1. Dekompresuje plik, który można pobrać, a następnie uruchom Visual Studio 2012.

  2. Na pasku menu wybierz kolejno opcje Plik, Otwórz i Projekt/rozwiązanie.

  3. Przejdź do folderu, który posiada zdekompresowany kod przykładu, a następnie otwórz plik rozwiązania (.sln) AsTaskWhenAnyDemoVB lub AsTaskWhenAnyDemoCS.

  4. W Eksploratorze rozwiązań otwórz menu skrótów dla projektu SequentialBlogReader, a następnie wybierz polecenie Ustaw jako projekt startowy.

  5. Wybierz klawisz F5, aby skompilować i uruchomić projekt.

  6. Uruchom kod kilka razy, aby sprawdzić, czy wyniki są wyświetlane każdorazowo w takiej samej kolejności.

Możesz ocenić plik MainPage.xaml.vb lub MainPage.xaml.cs w rozdziale Kompilacja kodu początkowego na końcu tematu.

Przykład jest oparty na czytniku blogów opisanym w Szybki Start: używanie operatora "await" dla programowania asynchronicznego.Jednak kod startowy dla tego tematu pobiera wiele źródeł danych blogów zamiast jednego.

Informacje na temat szerokiej gamy ulepszeń i rozszerzeń, które można wprowadzać w aplikacji – zobacz: Tworzenie czytnika bloga.

Pobieranie gotowych aplikacji

Jeśli nie chcesz samodzielnie utworzyć przykładu, możesz wczytać kompletny przykład.Postępuj zgodnie z instrukcjami w sekcji pobieranie początkowego kodu, ale wybierz WhenAnyBlogReader jako Projekt startowy.

Uruchom program kilka razy, aby sprawdzić, czy kanały bloga pojawiają się w różnych zleceniach.

Możesz ocenić plik MainPage.xaml.vb lub MainPage.xaml.cs w rozdziale Kompilacja ukończonej aplikacji na końcu tematu.

Kompilowanie kodu startowego

Możesz pobrać przykłady w tym temacie z Przykład async: Łączenie z .NET do Windows.Jeśli wolisz skonfigurować aplikację samodzielnie, wykonaj następujące kroki.

  1. Rozpocznij Visual Studio 2012.

  2. W pasku menu wybierz Plik, Nowy, Projekt.

    Zostanie otwarte okno dialogowe Nowy projekt.

  3. W kategorii Zainstalowane, Szablony wybierz Visual Basic lub Visual C#, a następnie wybierz polecenie Magazynu systemu Windows na liście typów projektów.

  4. Na liście typów projektów wybierz Pusta aplikacja (XAML).

  5. Nazwij projekt SequentialBlogReader, a następnie wybierz przycisk OK.

    W Eksploratorze rozwiązań pojawi się nowy projekt.

  6. W Eksploratorze rozwiązań, otwórz menu skrótówna MainPage.xaml oraz wybierz polecenie Otwórz.

  7. W oknie XAML pliku MainPage.xaml, zastąp kod następujący kod.

    <Page
        x:Class="SequentialBlogReader.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:AsTaskWhenAnyDemo"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Stretch" Margin="325,128,330,0" VerticalAlignment="Top" Click="StartButton_Click" Height="71" Background="#FFA89B9B" FontWeight="Bold" FontSize="36"/>
            <TextBox x:Name="ResultsTextBox" Margin="325,222,330,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" />
        </Grid>
    </Page>
    

    Proste okno zawierające pole tekstowe i przycisk pojawia się w oknie Projekt MainPage.xaml.

    Informacje na temat szerokiej gamy ulepszeń i rozszerzeń, które można wprowadzać w interfejsie użytkownika – zobacz: Tworzenie czytnika bloga.

  8. W Eksploratorze rozwiązań otwórz menu skrótów dla MainPage.xaml.vb lub MainPage.xaml.cs, a następnie wybierz polecenie Wyświetl kod.

  9. Zastąp kod w MainPage.xaml.vb lub MainPage.xaml.cs następującym kodem.

    ' Add an Imports statement for SyndicationClient. 
    Imports Windows.Web.Syndication
    
    
    ' The Blank Page item template is documented at http:'go.microsoft.com/fwlink/?LinkId=234238 
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
    
        End Sub 
    
    
        ' The async modifier enables you to use await in the event handler. 
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
            ResultsTextBox.Text = "" 
    
            ' Disable the button until the operation is complete.
            StartButton.IsEnabled = False 
    
            Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient()
    
            ' Force the SyndicationClient to download the information.
            client.BypassCacheOnRetrieve = True 
    
            Dim uriList = CreateUriList()
    
            Try 
                Dim feedsQuery As IEnumerable(Of IAsyncOperationWithProgress(Of SyndicationFeed, 
                                                                                RetrievalProgress)) =
                                                                From uri In uriList
                                                                Select client.RetrieveFeedAsync(uri)
    
                ' Run the query to start all the asynchronous processes. 
                Dim blogFeedOpsList As List(Of IAsyncOperationWithProgress(Of SyndicationFeed, 
                                                                           RetrievalProgress)) =
                                                               feedsQuery.ToList()
    
                Dim feed As SyndicationFeed
                For Each blogFeedOp In blogFeedOpsList
                    ' The Await operator retrieves the final result (a SyndicationFeed instance) 
                    ' from each IAsyncOperation instance.
                    feed = Await blogFeedOp
                    DisplayResults(feed)
                Next 
    
            Catch ex As Exception
                ResultsTextBox.Text =
                    "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
            End Try 
    
            ' Reenable the button in case you want to run the operation again.
            StartButton.IsEnabled = True 
        End Sub 
    
    
        Function CreateUriList() As List(Of Uri)
    
            ' Create a list of URIs. 
            Dim uriList = New List(Of Uri) From
            {
                    New Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
            }
            Return uriList
        End Function 
    
    
        Sub DisplayResults(sf As SyndicationFeed)
    
            ' Title of the blog.
            ResultsTextBox.Text &= sf.Title.Text & vbCrLf
    
            ' Titles and dates for blog posts. 
            For Each item As SyndicationItem In sf.Items
    
                ResultsTextBox.Text &= vbTab & item.Title.Text & ", " &
                                    item.PublishedDate.ToString() & vbCrLf
            Next
    
            ResultsTextBox.Text &= vbCrLf
        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 a using directive for SyndicationClient. 
    using Windows.Web.Syndication;
    
    
    namespace SequentialBlogReader
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                ResultsTextBox.Text = "";
    
                // Disable the button until the operation is complete.
                StartButton.IsEnabled = false;
    
                Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
    
                // Force the SyndicationClient to download the information.
                client.BypassCacheOnRetrieve = true;
    
                var uriList = CreateUriList();
    
                try
                {
                    IEnumerable<IAsyncOperationWithProgress<SyndicationFeed, 
                        RetrievalProgress>> feedsQuery = from uri in uriList
                                                         select client.RetrieveFeedAsync(uri);
    
                    // Run the query to start all the asynchronous processes.
                    List<IAsyncOperationWithProgress<SyndicationFeed, 
                        RetrievalProgress>> blogFeedOpsList = feedsQuery.ToList();
    
                    SyndicationFeed feed;
                    foreach (var blogFeedOp in blogFeedOpsList)
                    {
                        // The await operator retrieves the final result (a SyndicationFeed instance) 
                        // from each IAsyncOperation instance.
                        feed = await blogFeedOp;
                        DisplayResults(feed);
                    }
                }
                catch (Exception ex)
                {
                    ResultsTextBox.Text =
                        "Page could not be loaded.\n\r" + "Exception: " + ex.ToString();
                }
    
                // Reenable the button in case you want to run the operation again.
                StartButton.IsEnabled = true;
            }
    
            List<Uri> CreateUriList()
            {
                // Create a list of URIs.
                List<Uri> uriList = new List<Uri> 
                { 
                    new Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
                };
                return uriList;
            }
    
    
            void DisplayResults(SyndicationFeed sf)
            {
                // Title of the blog.
                ResultsTextBox.Text += sf.Title.Text + "\r\n";
    
                // Titles and dates for blog posts. 
                foreach (SyndicationItem item in sf.Items)
                {
                    ResultsTextBox.Text += "\t" + item.Title.Text + ", " +
                                        item.PublishedDate.ToString() + "\r\n";
                }
                ResultsTextBox.Text += "\r\n";
            }
        }
    }
    
  10. Wybierz klawisz F5, aby uruchomić program, a następnie wybierz przycisk Start.

Kompilowanie gotowych aplikacji

Możesz pobrać przykłady w tym temacie z Przykład async: Łączenie z .NET do Windows.Jeśli wolisz skonfigurować aplikację samodzielnie, wykonaj następujące kroki.

  1. Rozpocznij Visual Studio 2012.

  2. W pasku menu wybierz Plik, Nowy, Projekt.

    Zostanie otwarte okno dialogowe Nowy projekt.

  3. W kategorii Zainstalowane, Szablony wybierz Visual Basic lub Visual C#, a następnie wybierz polecenie Magazynu systemu Windows.

  4. Z listy typów projektów wybierz Pusta aplikacja (XAML).

  5. Nazwij projekt WhenAnyBlogReader, a następnie wybierz przycisk OK.

    W Eksploratorze rozwiązań pojawi się nowy projekt.

  6. W Eksploratorze rozwiązań, otwórz menu skrótówna MainPage.xaml oraz wybierz polecenie Otwórz.

  7. W oknie XAML pliku MainPage.xaml, zastąp kod następujący kod.

    <Page
        x:Class="WhenAnyBlogReader.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:AsTaskWhenAnyDemo"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Stretch" Margin="325,128,330,0" VerticalAlignment="Top" Click="StartButton_Click" Height="71" Background="#FFA89B9B" FontWeight="Bold" FontSize="36"/>
            <TextBox x:Name="ResultsTextBox" Margin="325,222,330,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" />
        </Grid>
    </Page>
    

    Proste okno zawierające pole tekstowe i przycisk pojawia się w oknie Projekt MainPage.xaml.

    Informacje na temat szerokiej gamy ulepszeń i rozszerzeń, które można wprowadzać w aplikacji – zobacz: Tworzenie czytnika bloga.

  8. W Eksploratorze rozwiązań otwórz menu skrótów dla MainPage.xaml.vb lub MainPage.xaml.cs, a następnie wybierz polecenie Wyświetl kod.

  9. Zastąp kod w MainPage.xaml.vb lub MainPage.xaml.cs następującym kodem.

    ' Add an Imports statement for SyndicationClient. 
    Imports Windows.Web.Syndication
    
    ' Add an Imports statement for the Tasks. 
    Imports System.Threading.Tasks
    
    ' The Blank Page item template is documented at http:'go.microsoft.com/fwlink/?LinkId=234238 
    
    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)
    
            ResultsTextBox.Text = "" 
    
            ' Disable the button until the operation is complete.
            StartButton.IsEnabled = False 
    
            Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient()
    
            ' Force the SyndicationClient to download the information.
            client.BypassCacheOnRetrieve = True 
    
            Dim uriList = CreateUriList()
    
            ' The following code avoids the use of implicit typing so that you  
            ' can see the types clearly. 
    
            Try 
                Dim feedsQuery As IEnumerable(Of Task(Of SyndicationFeed)) =
                    From uri In uriList
                    Select client.RetrieveFeedAsync(uri).AsTask()
                ' AsTask changes the returns from RetrieveFeedAsync into tasks. 
    
                ' Run the query to start all the asynchronous processes. 
                Dim blogFeedTasksList As List(Of Task(Of SyndicationFeed)) = feedsQuery.ToList()
    
                Dim feed As SyndicationFeed
    
                ' Repeat the following until there are no tasks left: 
                '    - Grab the first one that finishes. 
                '    - Retrieve the results from the task (what the return statement  
                '      in RetrieveFeedAsync returns). 
                '    - Remove the task from the list. 
                '    - Display the results. 
                While blogFeedTasksList.Count > 0
                    Dim nextTask As Task(Of SyndicationFeed) = Await Task.WhenAny(blogFeedTasksList)
                    feed = Await nextTask
                    blogFeedTasksList.Remove(nextTask)
                    DisplayResults(feed)
                End While 
    
            Catch ex As Exception
                ResultsTextBox.Text =
                    "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
            End Try 
    
            ' Reenable the button in case you want to run the operation again.
            StartButton.IsEnabled = True 
        End Sub 
    
    
        Function CreateUriList() As List(Of Uri)
    
            ' Create a list of URIs. 
            Dim uriList = New List(Of Uri) From
            {
                    New Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"),
                    New Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
            }
            Return uriList
        End Function 
    
    
        Sub DisplayResults(sf As SyndicationFeed)
    
            ' Title of the blog.
            ResultsTextBox.Text &= sf.Title.Text & vbCrLf
    
            ' Titles and dates for blog posts. 
            For Each item As SyndicationItem In sf.Items
    
                ResultsTextBox.Text &= vbTab & item.Title.Text & ", " &
                                    item.PublishedDate.ToString() & vbCrLf
            Next
    
            ResultsTextBox.Text &= vbCrLf
        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 a using directive for SyndicationClient. 
    using Windows.Web.Syndication;
    
    // Add a using directive for the Tasks. 
    using System.Threading.Tasks;
    
    
    namespace WhenAnyBlogReader
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
            }
    
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                ResultsTextBox.Text = "";
    
                // Disable the button until the operation is complete.
                StartButton.IsEnabled = false;
    
                Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
    
                // Force the SyndicationClient to download the information.
                client.BypassCacheOnRetrieve = true;
    
                var uriList = CreateUriList();
    
                // The following code avoids the use of implicit typing (var) so that you  
                // can identify the types clearly. 
    
                try
                {
                    IEnumerable<Task<SyndicationFeed>> feedsQuery =
                            from uri in uriList
                            // AsTask changes the returns from RetrieveFeedAsync into tasks. 
                            select client.RetrieveFeedAsync(uri).AsTask();
    
                    // Run the query to start all the asynchronous processes.
                    List<Task<SyndicationFeed>> blogFeedTasksList = feedsQuery.ToList();
    
                    SyndicationFeed feed;
    
                    // Repeat the following until no tasks remain: 
                    //    - Grab the first one that finishes. 
                    //    - Retrieve the results from the task (what the return statement  
                    //      in RetrieveFeedAsync returns). 
                    //    - Remove the task from the list. 
                    //    - Display the results. 
                    while (blogFeedTasksList.Count > 0)
                    {
                        Task<SyndicationFeed> nextTask = await Task.WhenAny(blogFeedTasksList);
                        feed = await nextTask;                    
                        blogFeedTasksList.Remove(nextTask);
                        DisplayResults(feed);
                    }
                }
                catch (Exception ex)
                {
                    ResultsTextBox.Text =
                        "Page could not be loaded.\n\r" + "Exception: " + ex.ToString();
                }
    
                // Reenable the button in case you want to run the operation again.
                StartButton.IsEnabled = true;
            }
    
    
            List<Uri> CreateUriList()
            {
                // Create a list of URIs.
                List<Uri> uriList = new List<Uri> 
                { 
                    new Uri("https://windowsteamblog.com/windows/b/developers/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/extremewindows/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/bloggingwindows/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
                };
                return uriList;
            }
    
    
            void DisplayResults(SyndicationFeed sf)
            {
                // Title of the blog.
                ResultsTextBox.Text += sf.Title.Text + "\r\n";
    
                // Titles and dates for blog posts. 
                foreach (SyndicationItem item in sf.Items)
                {
                    ResultsTextBox.Text += "\t" + item.Title.Text + ", " +
                                        item.PublishedDate.ToString() + "\r\n";
                }
                ResultsTextBox.Text += "\r\n";
            }
        }
    }
    
  10. Wybierz klawisz F5, aby uruchomić program, a następnie wybierz przycisk Start.

Zobacz też

Informacje

WhenAny``1

AsTask``1

Koncepcje

Programowanie asynchroniczne z Async i Await (C# i Visual Basic)

Anulowanie pozostałych zadań asynchronicznych po zakończeniu jednego (C# i Visual Basic)

Rozpoczynanie wielu zadań asynchronicznych i przetwarzanie ich w chwili zakończenia (C# i Visual Basic)

Inne zasoby

Quickstart: użycie operatora oczekiwania dla programowania asynchronicznego

Tworzenie czytnika bloga

IAsyncOperationWithProgress