Sdílet prostřednictvím


WhenAny: přemostění rozhraní .NET Framework a prostředí Windows Runtime (C# a Visual Basic)

Příklad v tomto tématu kombinuje typ prostředí Windows Runtime, který asynchronně stáhne kanály blogu pomocí metody rozhraní .NET Framework, která zpracovává asynchronní úlohy v pořadí, ve kterém jsou dokončeny.Další informace o tomto typu naleznete v části SyndicationClient.Další informace o metodě naleznete v tématu Task.WhenAny.

Kombinací těchto funkcí můžete začít stahovat současně více kanálů blogů a po jejich dokončení zpracovávat výsledky.Pokud jeden kanál stahuje rychleji než ostatní, jeho výsledky se zobrazují první.Pomocí metody SyndicationClient si můžete stáhnout informační kanály snadněji; pomocí metody Task.WhenAny můžete snadněji identifikovat další informační kanál, který dokončil stahování.

[!POZNÁMKA]

Chcete-li spustit příklad, musíte mít v počítači nainstalován systém Windows 8.Kromě toho, pokud chcete spustit příklad ze sady Visual Studio, musíte také mít nainstalováno Visual Studio 2012 Visual Studio 2013, Visual Studio Express 2012 pro Windows 8 nebo Visual Studio Express 2013 for Windows.

Následující kód je kombinací těchto funkcí z prostředí Windows Runtime a .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();
}

Vzorové postupy výstupu podobné následujícím řádkům:Pro každý blog zobrazuje displej název blogu následovaný názvy a termíny příspěvků do 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

Zbytek tohoto tématu obsahuje podrobnosti o postupu vytvoření příkladu a jak funguje.

Musíte mít v počítači nainstalováno Visual Studio 2012 a Windows 8 ke spuštění této aplikace.

Toto téma obsahuje následující oddíly.

  • Možnosti vytvoření příkladu
  • Princip počátečního kódu
  • Rozšíření počátečního kódu
  • Stažení počátečního kódu
  • Stažení kompletní aplikace
  • Vytvoření počátečního kódu
  • Vytvoření kompletní aplikace
  • Příbuzná témata

Možnosti vytvoření příkladu

Příklad vychází ze čtečky blogu popsané v části Rychlý start: použití operátora await pro asynchronní programování.Počáteční kód pro toto téma však stáhne více kanálů blogů, nikoli jen jeden.

Počáteční kód používá funkci prostředí Windows Runtime k postupnému stažení blogů kanálů.To znamená, že kanály blogů budou staženy v pořadí, ve kterém jsou uvedeny v kolekci adres URL.Aplikace po dokončení přidá funkce .NET Framework, se kterými můžete stahovat kanály blogu v pořadí, ve kterém byly dokončeny.

Vzorový kód můžete nastavit v některém z následujících způsobů:

  • Počáteční kód.

    • Počáteční kód můžete stáhnout pomocí pokynů v tématu Stažení počátečního kódu.

    • Počáteční kód můžete také vytvořit sami pomocí pokynů v tématu Tvorba počátečního kódu.

    • Můžete zkontrolovat počáteční kód bez implementace posunutím do Tvorba počátečního kódu.

  • Hotová aplikace

    • Můžete stáhnout také dokončenou aplikaci pomocí pokynů v tématu Stažení dokončené aplikace.

    • Aplikace můžete také sestavit sami pomocí pokynů v tématu Sestavení dokončené aplikace.

    • Dokončení aplikace můžete zkontrolovat bez její implementace posunutím do Tvorba dokončených aplikací.

Část Principy počátečního kódu popisuje klíčové body základního řešení.

Oddíl Rozšíření počátečního kódu popisuje, jak změnit kód přidáním parametrů AsTask``2 a Task.WhenAny.

Princip počátečního kódu

Počáteční kód používá metodu SyndicationClient, RetrieveFeedAsync ke stažení kanálu blogu z každého identifikátoru URI v seznamu identifikátorů URI.Každé volání metody vrátí instanci IAsyncOperationWithProgress, která reprezentuje probíhající asynchronní operaci.Když je očekáváno, vyvolá asynchronní operace instanci SyndicationFeed, která obsahuje informace o stažených zdrojích blogu.

Kód definuje dotaz, který aplikuje RetrieveFeedAsync u každé položky v seznamu identifikátorů URI.Při spuštění vrátí dotazu kolekci instance 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 spustí dotaz a začne asynchronní procesy, jak ukazuje následující kód.

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

V tomto okamžiku máte k dispozici seznam aktivních instancí IAsyncOperationWithProgress.Stále musíte očekávat každou instanci pro získání konečných výsledků.

Následující smyčka čeká na všechny instance IAsyncOperationWithProgress, než načte výsledky 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);
}

Můžete zkontrolovat tuto verzi programu v části Sestavování počátečního ku na konci tématu.

Můžete najít další informace o programování s asynchronními prostředí Windows Runtime rozhraními API v Quickstart: asynchronní programování pomocí operátoru await.

Rozšíření počátečního kódu

Počáteční kód ukazuje, že SyndicationClient usnadňuje stažení kanálů blogu.Zbývající krok pro dokončení příkladu je povolit aplikaci procesu, který blog seřadí do pořadí, ve kterém jejich stahování dokončeno místo v pořadí, v jakém jsou uvedeny v seznamu identifikátorů URI.

Klíčem k posílení je metoda Task.WhenAny.Pokud použijete WhenAny do kolekce asynchronních procesů, metoda vrátí první proces, který dokončí, a minimalizuje čas, který musíte počkat.V tomto případě není důležité pořadí zobrazení informací pro blog.Pokud je jedno stahování pomalé, zobrazí se první výsledky z jiného blogu.Situace se zdá být ideální pro WhenAny kromě jediného: WhenAny vyžaduje sadu úkolů.

Vyvolání AsTask

WhenAny vyžaduje sadu instancí Task nebo Task, ale metoda SyndicationClient, která stáhne kanály blogu, vrátí instanci IAsyncOperationWithProgress.Proto musí aplikace přemostit mezi objekty IAsyncOperationWithProgress z prostředí Windows Runtime a objekty Task z rozhraní .NET Framework.

Rozhraní .NET Framework poskytuje pro potřeby převodu rozšiřující metody AsTask``2.Při vyvolání AsTask instance IAsyncOperationWithProgress vrátí AsTask úlohu, která představuje asynchronní operaci.Úkol je dokončen, když odpovídající instance IAsyncOperationWithProgress je dokončena a úkol má výsledek nebo výjimku instance.

Proto stačí vyvolat AsTask na každé instanci IAsyncOperationWithProgress, která vrátí RetrieveFeedAsync, jak ukazuje následující kód.Kód pro přehlednost přejmenuje proměnné tak, aby odrážely změny úkolů, a aby používaly explicitní styl zadání.

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

[!POZNÁMKA]

AsTask hraje v asynchronním programování důležitou roli, které si pravděpodobně nejste vědomi.Kompilátor používá AsTask pokaždé, když použijete operátor await v instanci IAsyncAction nebo IAsyncOperation (viz následující kód).

Použití WhenAny

Posledním krokem v převodu je přidání metody Task.WhenAny do aplikace.WhenAny se použije na kolekci úkolů (blogFeedTasksList) a vrátí první úkol v kolekci, která bude dokončena.Přesněji řečeno, WhenAny vrátí úkol, který se při očekávání vyhodnocuje u nejprve dokončeného úkolu.

Následující příkaz volá WhenAny a čeká výsledek.Kód pro větší přehlednost zobrazení výsledků využívá explicitní zadání.

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

Následující kód provede totéž, jako předchozí prohlášení, ale operaci rozdělí na dva příkazy pro lepší přehled toho, co se stane.První příkaz volá funkci WhenAny a druhý příkaz čeká na výsledek.

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

Nakonec musíte počkat, až nextTask načte výsledky (instance SyndicationFeed) z úkolu, který byl dokončen jako první, a poté je nutné odebrat nextTask ze seznamu, aby nebyl znovu zpracován.

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

Použijte cyklus while k provedení tohoto postupu pro každý úkol v 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);
}

Můžete zkontrolovat tuto verzi programu v části Sestavování dokončené aplikace na konci tématu.Nebo můžete postupovat podle pokynů v části Stahování dokončené aplikace a projekt stáhnout.

Poznámka k upozorněníUpozornění

Použití WhenAny ve smyčce, jak je popsáno v příkladu, je v pořádku pro problémy, které se týkají malého počtu úkolů.Další postupy jsou však efektivnější, pokud máte velký počet úkolů zpracovat.Další informace a příklady naleznete v tématu Zpracování úkolů při jejich dokončování.

Stažení počátečního kódu

Můžete si stáhnout počáteční kód například z Asynchronní vzorek: Přemostění z .NET do systému Windows.Pokud nemáte přístup k Internetu, postupujte podle pokynů v části Building the Starter Code na konci tohoto tématu pro vytvoření počátečního kódu.

Po stažení kódu jej můžete otevřít a spustit pomocí následujících kroků.

  1. Dekomprimujte soubor, který jste stáhli a poté spusťte Visual Studio 2012.

  2. Na panelu nabídky vyberte možnosti Soubor, Otevřít, Projekt/řešení.

  3. Přejděte do složky obsahující dekomprimovaný ukázkový kód a otevřete soubor řešení (.sln) pro AsTaskWhenAnyDemoVB nebo AsTaskWhenAnyDemoCS.

  4. Průzkumníku řešení otevřete místní nabídku projektu SequentialBlogReader a vyberte položku Nastavit jako položku po spuštění.

  5. Sestavte a spusťte projekt tlačítkem F5.

  6. Kód několikrát spusťte a ověřte tak, že se výsledky vždy zobrazí ve stejném pořadí.

Můžete zkontrolovat soubor MainPage.xaml.vb nebo MainPage.xaml.cs v části Tvorba počátečního kódu na konci tohoto tématu.

Příklad vychází ze čtečky blogu popsané v části Rychlý start: použití operátora await pro asynchronní programování.Počáteční kód pro toto téma však stáhne více kanálů blogů, nikoli jen jeden.

Informace o řadě vylepšení a rozšíření, které je možné vytvořit pro aplikaci, naleznete v tématu Vytvořit čtečku blogů.

Stažení kompletní aplikace

Pokud nechcete sestavovat tento příklad sami, můžete si stáhnout kompletní příklad.Postupujte podle pokynů v části Stahování počátečního kódu, ale zvolte možnost WhenAnyBlogReader v části Spuštěný projekt.

Program několikrát spusťte a ověřte tak, že se kanály blogů zobrazí v různém pořadí.

Můžete zkontrolovat soubor MainPage.xaml.vb nebo MainPage.xaml.cs v části Tvorba dokončené aplikace na konci tématu.

Vytvoření počátečního kódu

Můžete si stáhnout příklady v tomto tématu z Asynchronní vzorek: Přemostění z .NET do systému Windows.Pokud chcete nastavit aplikaci sami, postupujte takto.

  1. Spusťte Visual Studio 2012.

  2. Na panelu nabídky vyberte možnosti Soubor, Nový, Projekt.

    Otevře se dialogové okno Nový projekt.

  3. V kategorii Nainstalováno, Šablony zvolte možnost Visual Basic nebo Visual C# a pak v seznamu typů projektů zvolte možnost Úložiště systému Windows.

  4. V seznamu typy projektů, klepněte na příkaz Prázdná aplikace (XAML).

  5. Pojmenujte projekt SequentialBlogReader a stiskněte tlačítko OK.

    V podokně Průzkumník řešení se zobrazí nový projekt.

  6. V Průzkumníku řešení otevřete místní nabídku pro MainPage.xaml a pak zvolte Otevřít.

  7. V okně XAML pro soubor MainPage.xaml nahraďte kód následujícím kódem.

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

    Jednoduché okno obsahující textové pole a tlačítko se zobrazí v okně Návrh souboru MainPage.xaml.

    Informace o řadě vylepšení a rozšíření, které je možné vytvořit pro uživatelské rozhraní, naleznete v tématu Vytvořit čtečku blogů.

  8. V Průzkumníku řešení otevřete místní nabídku pro soubor MainPage.xaml nebo MainPage.xaml.cs a pak zvolte možnost Zobrazit kód.

  9. Nahraďte kód pro MainPage.xaml.vb nebo MainPage.xaml.cs za následující kód.

    ' 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. Zvolte klávesu F5 ke spuštění programu a pak zvolte tlačítko Start.

Vytvoření kompletní aplikace

Můžete si stáhnout příklady v tomto tématu z Asynchronní vzorek: Přemostění z .NET do systému Windows.Pokud chcete nastavit aplikaci sami, postupujte takto.

  1. Spusťte Visual Studio 2012.

  2. Na panelu nabídky vyberte možnosti Soubor, Nový, Projekt.

    Otevře se dialogové okno Nový projekt.

  3. V kategorii Nainstalováno, Šablony zvolte možnost Visual Basic nebo Visual C# a pak zvolte možnost Úložiště systému Windows.

  4. V seznamu typy projektů klepněte na příkaz Prázdná aplikace (XAML).

  5. Pojmenujte projekt WhenAnyBlogReader a stiskněte tlačítko OK.

    V podokně Průzkumník řešení se zobrazí nový projekt.

  6. V Průzkumníku řešení otevřete místní nabídku pro MainPage.xaml a pak zvolte Otevřít.

  7. V okně XAML pro soubor MainPage.xaml nahraďte kód následujícím kódem.

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

    Jednoduché okno obsahující textové pole a tlačítko se zobrazí v okně Návrh souboru MainPage.xaml.

    Informace o řadě vylepšení a rozšíření, které je možné vytvořit pro aplikaci, naleznete v tématu Vytvořit čtečku blogů.

  8. V Průzkumníku řešení otevřete místní nabídku pro soubor MainPage.xaml nebo MainPage.xaml.cs a pak zvolte možnost Zobrazit kód.

  9. Nahraďte kód pro MainPage.xaml.vb nebo MainPage.xaml.cs za následující kód.

    ' 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. Zvolte klávesu F5 ke spuštění programu a pak zvolte tlačítko Start.

Viz také

Referenční dokumentace

WhenAny``1

AsTask``1

Koncepty

Asynchronní programování pomocí modifikátoru Async a operátoru Await (C# a Visual Basic)

Zrušení zbývajících asynchronních úloh po dokončení jedné z nich (C# a Visual Basic)

Zahájení více úloh s modifikátorem Async a jejich zpracování po dokončení (C# a Visual Basic)

Další zdroje

Quickstart: použití operátoru await pro asynchronní programování

Vytvořit čtečku blogů

IAsyncOperationWithProgress