Condividi tramite


WhenAny: bridging tra .NET Framework e Windows Runtime (C# e Visual Basic)

L'esempio riportato in questo argomento combina un tipo di Windows Runtime che scarica feed di blog in modo asincrono con un metodo di .NET Framework che elabora attività asincrone nell'ordine in cui vengono completate. Per ulteriori informazioni sul tipo, vedere SyndicationClient. Per ulteriori informazioni sul metodo, vedere Task.WhenAny.

Combinando queste funzionalità, è possibile iniziare a scaricare contemporaneamente più feed del blog ed elaborare i risultati durante il completamento. Se un feed viene scaricato più rapidamente degli altri, i risultati vengono visualizzati per primi. Utilizzando un metodo SyndicationClient, è possibile scaricare i feed più facilmente; tramite il metodo Task.WhenAny, è invece possibile identificare con maggiore facilità il feed successivo che è stato scaricato.

Nota

Per eseguire l'esempio, è necessario che Windows 8 sia installato nel computer.Inoltre, se si desidera eseguire l'esempio da Visual Studio, è necessario che Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 per Windows 8 o Visual Studio Express 2013 per Windows siano installati.

Il seguente codice combina le funzionalità da Windows Runtime e .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();
}

L'output generato nell'esempio precedente è simile a quello mostrato nelle righe seguenti. Per ogni blog, viene mostrato il titolo del blog seguito dai titoli e dalle date dei post del blog.

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

Il resto di questo argomento fornisce informazioni dettagliate su come creare l'esempio e sul suo funzionamento.

Per eseguire questa applicazione, è necessario che nel computer sia installato Visual Studio 2012 e Windows 8.

Di seguito sono elencate le diverse sezioni di questo argomento.

  • Opzioni di installazione per l'esempio
  • Informazioni sul codice iniziale
  • Estensione del codice iniziale
  • Download del codice di avvio
  • Download dell'applicazione finita
  • Compilazione del codice iniziale
  • Compilazione dell'applicazione finita
  • Argomenti correlati

Opzioni di installazione per l'esempio

L'esempio è basato sul lettore di blog descritto in Guida rapida: utilizzo dell'operatore await per la programmazione asincrona. Tuttavia, il codice iniziale per questo argomento scarica più feed del blog anziché uno.

Il codice iniziale utilizza la funzionalità di Windows Runtime per scaricare i feed di blog in sequenza. Ovvero i feed di blog vengono scaricati nell'ordine in cui sono elencati in una raccolta di URL. L'applicazione completata aggiunge la funzionalità da .NET Framework per scaricare i feed di blog nell'ordine in cui vengono completati.

È possibile installare il codice di esempio in uno dei seguenti modi:

  • Codice iniziale.

    • È possibile scaricare il codice iniziale seguendo le istruzioni riportate in Downloading the Starter Code.

    • È possibile creare il codice iniziale manualmente seguendo le istruzioni riportate in Building the Starter Code.

    • È possibile esaminare il codice iniziale senza implementarlo passando a Building the Starter Code.

  • Applicazione terminata.

    • È possibile scaricare l'applicazione finita seguendo le istruzioni in Downloading the Finished App

    • È possibile compilare l'applicazione personalmente seguendo le istruzioni riportate in Building the Finished App.

    • È possibile esaminare l'applicazione completata senza implementarla passando a Building the Finished App.

Nella sezione Understanding the Starter Code vengono illustrati i punti chiave della soluzione di base.

Nella sezione Extending the Starter Code viene illustrato come modificare il codice aggiungendo AsTask``2 e Task.WhenAny.

Informazioni sul codice iniziale

Il codice iniziale utilizza un metodo SyndicationClient, RetrieveFeedAsync, per scaricare un feed di blog da ciascun URI nell'elenco degli URI. Ogni chiamata al metodo restituisce un'istanza IAsyncOperationWithProgress che rappresenta un'operazione asincrona in corso. Una volta attesa, l'operazione asincrona genera l'istanza della classe SyndicationFeed che contiene informazioni sul feed di blog scaricato.

Il codice definisce una query che applica RetrieveFeedAsync a ogni voce in un elenco di URI. Una volta eseguita, la query restituisce una raccolta di istanze di 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 esegue la query e avvia i processi asincroni, come illustrato nel codice seguente.

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

A questo punto, si dispone di un elenco di istanze di IAsyncOperationWithProgress attive. È necessario attendere ogni istanza per ottenere i risultati finali.

Il seguente ciclo attende ogni istanza di IAsyncOperationWithProgress per recuperare i risultati di 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);
}

È possibile esaminare questa versione del programma nella sezione Building the Starter Code alla fine dell'argomento.

Ulteriori informazioni sulla programmazione con API di Windows Runtime asincrone sono disponibili in Guida introduttiva: Chiamata di API asincrone in C# o Visual Basic.

Estensione del codice iniziale

Il codice iniziale dimostra che SyndicationClient rende più semplice il download di feed di blog. Il passaggio rimanente per completare l'esempio prevede l'abilitare l'applicazione a elaborare i feed di blog nell'ordine in cui vengono completati i download anziché nell'ordine in cui appaiono nell'elenco degli URI.

La chiave per eseguire l'aggiornamento è il metodo Task.WhenAny. Quando si applica WhenAny a una raccolta di processi asincroni, il metodo restituisce il primo processo che completa, riducendo al minimo il tempo di attesa. In questo esempio l'ordine in cui vengono visualizzate le informazioni di un feed del blog non è significativo. Se un download è lento, i risultati di un altro blog possono essere visualizzati per primi. La situazione è perfetta per WhenAny ad eccezione di una cosa: WhenAny richiede una raccolta di attività.

Chiamata di AsTask

WhenAny richiede una raccolta di istanze di Task o Task, ma il metodo SyndicationClient che scarica i feed del blog restituisce un'istanza dell'interfaccia IAsyncOperationWithProgress. Pertanto, l'applicazione deve creare un ponte tra gli oggetti IAsyncOperationWithProgress da Windows Runtime e gli oggetti Task da .NET Framework.

.NET Framework fornisce metodi di estensione AsTask``2 per eseguire la transizione. Quando si richiama AsTask in un'istanza di IAsyncOperationWithProgress, AsTask restituisce un'attività che rappresenta l'operazione asincrona. L'attività viene completata quando viene completata la corrispondente istanza di IAsyncOperationWithProgress e l'attività presenta il risultato dell'istanza o un'eccezione.

Pertanto, si richiama semplicemente AsTask in ogni istanza di IAsyncOperationWithProgress che RetrieveFeedAsync restituisce, come mostrato nel codice seguente. Il codice rinomina le variabili per riflettere la modifica alle attività e utilizza la tipizzazione esplicita per semplificare la leggibilità.

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

Nota

AsTask gioca un ruolo importante nella programmazione asincrona più di quanto si immagini.Il compilatore utilizza AsTask ogni volta che viene applicato un operatore await a un'istanza di IAsyncAction o IAsyncOperation, come indicato nel codice seguente.

Applicazione di WhenAny

L'ultimo passaggio della conversione consiste nell'aggiungere il metodo Task.WhenAny all'applicazione. WhenAny viene applicato a una raccolta di attività (blogFeedTasksList) e restituisce la prima attività nella raccolta che completa. In particolare, WhenAny restituisce un'attività che, se attesa, restituisce l'attività completata per prima.

La seguente istruzione chiama WhenAny e attende il risultato. Il codice utilizza la tipizzazione esplicita per illustrare il risultato più chiaramente.

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

Il codice seguente fa la stessa cosa dell'istruzione precedente ma scompone l'operazione in due istruzioni per maggiore chiarezza. La prima istruzione chiama WhenAny e la seconda istruzione attende il risultato.

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

Infine, è necessario attendere nextTask per recuperare i risultati (istanza di SyndicationFeed ) dall'attività che ha terminato per prima ed è quindi necessario rimuovere nextTask dall'elenco in modo da non elaborarlo nuovamente.

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

Utilizzare un ciclo while per eseguire questi passaggi per ogni attività in 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);
}

È possibile esaminare questa versione del programma nella sezione Building the Finished App alla fine dell'argomento. Oppure è possibile seguire le istruzioni in Downloading the Finished App per scaricare il progetto.

Avviso

L'utilizzo di WhenAny in un ciclo, come descritto nell'esempio, è adatto ai problemi che coinvolgono un numero limitato di attività.Tuttavia, altri approcci sono più efficaci se si dispone di numerose attività da elaborare.Per ulteriori informazioni ed esempi, vedere Attività di elaborazione mano a mano che vengono completate.

Download del codice di avvio

È possibile scaricare il codice iniziale per l'esempio da Esempio asincrono: Bridging da .NET a Windows. Se non si ha accesso a Internet, seguire le istruzioni in Compilazione del codice iniziale alla fine di questo argomento per creare il codice iniziale.

Una volta scaricato il codice, è possibile aprirlo ed eseguirlo completando i passaggi seguenti.

  1. Decomprimere il file scaricato, quindi avviare Visual Studio 2012.

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

  3. Passare alla cartella che contiene il codice di esempio decompresso e aprire il file di soluzione (con estensione sln) per AsTaskWhenAnyDemoVB o AsTaskWhenAnyDemoCS.

  4. In Esplora soluzioni aprire il menu di scelta rapida per il progetto SequentialBlogReader, quindi scegliere Imposta come progetto di avvio.

  5. Premere il tasto F5 per compilare ed eseguire il progetto.

  6. Eseguire il codice più volte per verificare che i risultati vengano visualizzati ogni volta nello stesso ordine.

È possibile esaminare il file MainPage.xaml.vb o MainPage.xaml.cs nella sezione Building the Starter Code alla fine dell'argomento.

L'esempio è basato sul lettore di blog descritto in Guida rapida: utilizzo dell'operatore await per la programmazione asincrona. Tuttavia, il codice iniziale per questo argomento scarica più feed del blog anziché uno.

Per informazioni su un'ampia varietà di miglioramenti e di estensioni che è possibile apportare all'applicazione, vedere Creare un lettore di blog.

Download dell'applicazione finita

Se non si desidera compilare l'esempio autonomamente, è possibile scaricare l'esempio completo. Seguire le istruzioni nella sezione Download del codice di avvio, ma scegliere WhenAnyBlogReader come Progetto di avvio.

Eseguire il programma più volte per verificare che i feed di blog vengano visualizzati in ordini diversi.

È possibile esaminare il file MainPage.xaml.vb o MainPage.xaml.cs nella sezione Building the Finished App alla fine dell'argomento.

Compilazione del codice iniziale

È possibile scaricare gli esempi di questo argomento da Esempio asincrono: Bridging da .NET a Windows. Se si desidera impostare l'applicazione con l'utente corrente, attenersi alla seguente procedura.

  1. Avviare Visual Studio 2012.

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

    Verrà visualizzata la finestra di dialogo Nuovo progetto.

  3. Nella categoria Installato, Modelli scegliere Visual Basic o Visual C#, quindi Windows Store dall'elenco di tipi di progetto.

  4. Nell'elenco dei tipi di progetto selezionare Applicazione vuota (XAML).

  5. Assegnare il nome SequentialBlogReader al progetto, quindi selezionare il pulsante OK.

    Il nuovo progetto verrà visualizzato in Esplora soluzioni.

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

  7. Nella finestra XAML di MainPage.xaml sostituire il codice con il seguente.

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

    Viene visualizzata una semplice finestra che contiene una casella di testo e un pulsante nella finestra Progettazione di MainPage.xaml.

    Per informazioni su un'ampia varietà di miglioramenti e di estensioni che è possibile apportare all'interfaccia utente, vedere Creare un lettore di blog.

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

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

    ' 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. Premere il tasto F5 per eseguire il programma, quindi scegliere il pulsante Avvia.

Compilazione dell'applicazione finita

È possibile scaricare gli esempi di questo argomento da Esempio asincrono: Bridging da .NET a Windows. Se si desidera impostare l'applicazione con l'utente corrente, attenersi alla seguente procedura.

  1. Avviare Visual Studio 2012.

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

    Verrà visualizzata la finestra di dialogo Nuovo progetto.

  3. Nella categoria Installato, Modelli scegliere Visual Basic o Visual C#, quindi Windows Store.

  4. Nell'elenco dei tipi di progetto selezionare Applicazione vuota (XAML).

  5. Assegnare il nome WhenAnyBlogReader al progetto, quindi selezionare il pulsante OK.

    Il nuovo progetto verrà visualizzato in Esplora soluzioni.

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

  7. Nella finestra XAML di MainPage.xaml sostituire il codice con il seguente.

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

    Viene visualizzata una semplice finestra che contiene una casella di testo e un pulsante nella finestra Progettazione di MainPage.xaml.

    Per informazioni su un'ampia varietà di miglioramenti e di estensioni che è possibile apportare all'applicazione, vedere Creare un lettore di blog.

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

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

    ' 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. Premere il tasto F5 per eseguire il programma, quindi scegliere il pulsante Avvia.

Vedere anche

Riferimenti

AsTask``1

WhenAny``1

Concetti

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

Annullare le attività asincrone rimanenti dopo che ne è stata completata una (C# e Visual Basic)

Avviare più attività asincrone ed elaborarle quando vengono completate (C# e Visual Basic)

Altre risorse

Guida rapida: utilizzare l'operatore await per la programmazione asincrona

Creare un lettore di blog

IAsyncOperationWithProgress