WhenAny: Puente entre .NET Framework y Windows en tiempo de ejecución (C# y Visual Basic)

El ejemplo de este tema combina Windows en tiempo de ejecución cuyas descargue blogs de forma asincrónica con un método de .NET Framework que procesa tareas asincrónicas en el orden en que se completa.Para obtener más información sobre el tipo, vea SyndicationClient.Para obtener más información sobre el método, vea Task.WhenAny.

Combinando estas características, puede empezar a descargar las fuentes varias blog simultáneamente y procesar los resultados como finalizado.Si una fuente descarga más rápidamente que otras, los resultados aparecen primero.Utilizando un método de SyndicationClient, puede descargar las fuentes más fácilmente; utilizando el método de Task.WhenAny, le resultará más fácil identificar la fuente siguiente que es el descargar finalizado.

[!NOTA]

Para ejecutar el ejemplo, debe tener Windows 8 instalado en el equipo.Además, si desea ejecutar el ejemplo desde Visual Studio, también debe tener Visual Studio 2012 o Visual Studio Express 2012 para Windows 8 instalado.

El código siguiente combina estas características de Windows en tiempo de ejecución y de .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();
}

El ejemplo genera la salida que se parece a las líneas siguientes.Para cada blog, la pantalla muestra el título del blog seguido por los títulos y las fechas de las entradas de 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

El resto de este tema se proporcionan detalles sobre cómo crear el ejemplo y cómo funciona.

Debe tener Visual Studio 2012 y Windows 8 instalados en el equipo para ejecutar esta aplicación.

Este tema contiene las secciones siguientes.

  • Opciones de configuración para el ejemplo
  • Introducción al código de Starter
  • Extender el código de Starter
  • Descargar el código de Starter
  • Descargar la aplicación finalizada
  • Compilar el código de Starter
  • Compilar la aplicación finalizada
  • Temas relacionados

Opciones de configuración para el ejemplo

El ejemplo se basa en el lector de blog que se describe en QuickStart: mediante el operador aguardar para programación asincrónica.Sin embargo, el código de inicio de este tema descarga proporciona varios blog en lugar de solo una.

El código de inicio utiliza la funcionalidad de Windows en tiempo de ejecución para descargar blogs secuencialmente.Es decir, blogs se descargan en el orden en que se muestran en una colección de direcciones URL.La aplicación acabada agrega funcionalidad de .NET Framework para descargar blogs en el orden en que se completa.

Puede configurar el código de ejemplo de cualquiera de las maneras siguientes:

  • Código de Starter.

    • Puede descargar el código iniciador siguiendo las instrucciones de Descargar el código de Starter,

    • Puede crear el código de inicio personalmente siguiendo las instrucciones de Compilar el código de Starter.

    • Puede revisar el código iniciador sin implementarlo por moviéndose a Compilar el código de Starter.

  • Aplicación finalizada.

    • Puede descargar la aplicación acabada siguiendo las instrucciones de Descargar la aplicación finalizada

    • Puede compilar la aplicación usted mismo siguiendo las instrucciones de Compilar la aplicación finalizada.

    • Puede revisar la aplicación acabada sin implementarla moviéndose a Compilar la aplicación finalizada.

La sección de Introducción al código de Starter describe los puntos clave de la solución básica.

La sección de Extender el código de Starter muestra cómo modificar el código agregando AsTask y Task.WhenAny.

Introducción al código de Starter

El código de inicio utiliza un método de SyndicationClientRetrieveFeedAsync, para descargar una fuente de blog de cada URI en una lista de URI.Cada llamada al método devuelve IAsyncOperationWithProgress una instancia que representa una operación asincrónica en curso.Cuando se aguardada, la operación asincrónica genera SyndicationFeed una instancia que contiene información sobre la fuente descargado blog.

El código define una consulta que aplique RetrieveFeedAsync a cada entrada en una lista de URI.Cuando se ejecuta, la consulta devuelve una colección de instancias de 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<TSource> ejecuta la consulta y iniciar los procesos asincrónicos, como muestra el código siguiente.

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

En este punto, tiene una lista de instancias activas de IAsyncOperationWithProgress.Todavía debe aguardar cada instancia para obtener resultados finales.

El bucle siguiente espera cada instancia de IAsyncOperationWithProgress para recuperar los resultados de 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);
}

Puede revisar esta versión de programa en la sección de Building the Starter Code al final del tema.

Puede encontrar más información sobre la programación con Windows en tiempo de ejecución asincrónico API en QuickStart: mediante el operador aguardar para programación asincrónica.

Extender el código de Starter

El código de inicio muestra que SyndicationClient facilita descargar blogs.El paso restante para completar el ejemplo es habilitar la aplicación para procesar blogs en el orden en que las descargas completa en lugar del orden en que aparecen en la lista de URI.

La clave para lograr el aumento es el método de Task.WhenAny.Cuando se aplica WhenAny a una colección de procesos asincrónicos, el método devuelve el primer proceso completarse, se reduce el tiempo que se debe esperar.En este ejemplo, el orden en el que la información de la fuente de blog aparece no es importante.Si una descarga lenta, los resultados de otro blog pueden mostrar primero.La situación es perfecta para WhenAny salvo una acción: WhenAny requiere una colección de tareas.

JJ635140.collapse_all(es-es,VS.110).gifInvocar AsTask

WhenAny requiere una colección de Task o instancias de Task<TResult>, pero el método de SyndicationClient que descarga el blog alimenta devuelve IAsyncOperationWithProgress una instancia.Por tanto, la aplicación debe puente entre los objetos de IAsyncOperationWithProgress de Windows en tiempo de ejecución y los objetos de Task de .NET Framework.

.NET Framework proporciona métodos de extensión de AsTask para crear la transición.Cuando se invoca AsTask en una instancia de IAsyncOperationWithProgress, AsTask devuelve una tarea que representa la operación asincrónica.La tarea se completa cuando la instancia correspondiente de IAsyncOperationWithProgress completa, y la tarea tiene el resultado o excepción de instancia.

Por consiguiente, únicamente se invoca AsTask en cada instancia de IAsyncOperationWithProgress que RetrieveFeedAsync devuelve, como muestra el código siguiente.El código cambia variables para reflejar el cambio a tareas y utiliza un tipo explícito para mayor claridad.

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 desempeña un rol importante en la programación async que no es probable en cuenta.El compilador utiliza AsTask siempre que aplique un operador aguardar a una instancia de IAsyncAction o de IAsyncOperation, como muestra el código siguiente.

JJ635140.collapse_all(es-es,VS.110).gifWhenAny que aplica

El último paso en la conversión es agregar el método de Task.WhenAny a la aplicación.WhenAny se aplica a una colección de tareas (blogFeedTasksList) y devuelve la primera tarea a la colección que completa.Más específicamente, WhenAny devuelve una tarea que, cuando se aguardada, evalúe a la tarea que finalizó primero.

La instrucción siguiente llama a WhenAny y espera el resultado.El código utiliza un tipo explícito para mostrar el resultado más claramente.

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

El código siguiente hace lo mismo que la instrucción anterior pero interrumpe la operación en dos instrucciones para claro qué ocurre.La primera instrucción llama WhenAny, y la segunda instrucción espera el resultado.

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

Por último, debe aguardar nextTask para recuperar los resultados (una instancia de SyndicationFeed ) de la tarea que finalizó primero y, a continuación debe quitar nextTask de la lista de modo que no la procesar de nuevo.

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

Utilice un bucle while para realizar estos pasos para cada tarea en 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);
}

Puede revisar esta versión de programa en la sección de Compilar la aplicación finalizada al final del tema.O puede seguir las instrucciones de Descargar la aplicación finalizada de descargar el proyecto.

Nota de precauciónPrecaución

El uso de WhenAny en un bucle, como se describe en el ejemplo, está bien para los problemas que implican una pequeña cantidad de tareas.Sin embargo, otros enfoques son más eficientes si tiene un gran número de tareas que procesar.Para obtener más información y ejemplos, vea Tareas de procesamiento como completa.

Descargar el código de Starter

Puede descargar el código de inicio para el ejemplo de Ejemplo Async: Puente de .NET en Windows.Si no tiene acceso a internet, siga las instrucciones de Compilar el código de Starter al final de este tema para crear el código de inicio.

Después de descargar el código, abra y lo ejecuta siguiendo estos pasos.

  1. Descomprima el archivo que ha descargado, y comienza Visual Studio 2012.

  2. En la barra de menú, elija Archivo, Abrir, Proyecto/Solución.

  3. Navegue a la carpeta que contiene el código de ejemplo descomprimido, y abra el archivo de solución (.sln) para AsTaskWhenAnyDemoVB o AsTaskWhenAnyDemoCS.

  4. En Explorador de soluciones, abra el menú contextual para el proyecto SequentialBlogReader y, a continuación Establecer como proyecto de inicio.

  5. Elija la tecla F5 para compilar y ejecutar el proyecto.

  6. Ejecute el código varias veces para comprobar que los resultados aparecen en el mismo orden cada vez.

Puede revisar el archivo de MainPage.xaml.vb o de MainPage.xaml.cs en la sección de Compilar el código de Starter al final del tema.

El ejemplo se basa en el lector de blog que se describe en QuickStart: mediante el operador aguardar para programación asincrónica.Sin embargo, el código de inicio de este tema descarga proporciona varios blog en lugar de solo una.

Para obtener información sobre una gran variedad de mejoras y de extensiones que puede contener a la aplicación, vea Cree un lector de blog.

Descargar la aplicación finalizada

Si no desea compilar el ejemplo personalmente, puede descargar el ejemplo completo.Siga las instrucciones de la sección de Descargar el código de Starter, pero elija WhenAnyBlogReader como proyecto de inicio.

Ejecute el programa varias veces para comprobar que blogs aparecen en distintas pedidos.

Puede revisar el archivo de MainPage.xaml.vb o de MainPage.xaml.cs en la sección de Compilar la aplicación finalizada al final del tema.

Compilar el código de Starter

Puede descargar los ejemplos de este tema de Ejemplo Async: Puente de .NET en Windows.Si prefiere establecer la aplicación sobre sí mismo, siga estos pasos.

  1. Inicie Visual Studio 2012.

  2. En la barra de menú, elija Archivo, Nuevo, Proyecto.

    Aparece el cuadro de diálogo Nuevo proyecto.

  3. En Instalado, categoría Plantillas, elija Visual Basic o en Visual c# y, a continuación Tienda Windows en la lista de tipos de proyecto.

  4. En la lista de tipos de proyecto, elija Aplicación en blanco (XAML).

  5. Asigne al proyecto SequentialBlogReader, y elija el botón Aceptar.

    El nuevo proyecto aparecerá en el Explorador de soluciones.

  6. En Explorador de soluciones, abra el menú contextual para MainPage.xaml y, a continuación Abrir.

  7. En la ventana XAML de MainPage.xaml, reemplace el código por el código siguiente.

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

    Una ventana simple que contiene un cuadro de texto y un botón aparece en la ventana Diseñar de MainPage.xaml.

    Para obtener información sobre una gran variedad de mejoras y de extensiones que puede contener a la interfaz de usuario, vea Cree un lector de blog.

  8. En Explorador de soluciones, abra el menú contextual para MainPage.xaml.vb o MainPage.xaml.cs y, a continuación ver código.

  9. Reemplace el código de MainPage.xaml.vb o MainPage.xaml.cs con el código siguiente.

    ' 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. Presione la tecla F5 para ejecutar el programa y, a continuación, elija el botón Iniciar.

Compilar la aplicación finalizada

Puede descargar los ejemplos de este tema de Ejemplo Async: Puente de .NET en Windows.Si prefiere establecer la aplicación sobre sí mismo, siga estos pasos.

  1. Inicie Visual Studio 2012.

  2. En la barra de menú, elija Archivo, Nuevo, Proyecto.

    Aparece el cuadro de diálogo Nuevo proyecto.

  3. En Instalado, categoría Plantillas, elija Visual Basic o en Visual c# y, a continuación Tienda Windows.

  4. En la lista de tipos de proyecto, elija Aplicación en blanco (XAML).

  5. Asigne al proyecto WhenAnyBlogReader, y elija el botón Aceptar.

    El nuevo proyecto aparecerá en el Explorador de soluciones.

  6. En Explorador de soluciones, abra el menú contextual para MainPage.xaml y, a continuación Abrir.

  7. En la ventana XAML de MainPage.xaml, reemplace el código por el código siguiente.

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

    Una ventana simple que contiene un cuadro de texto y un botón aparece en la ventana Diseñar de MainPage.xaml.

    Para obtener información sobre una gran variedad de mejoras y de extensiones que puede contener a la aplicación, vea Cree un lector de blog.

  8. En Explorador de soluciones, abra el menú contextual para MainPage.xaml.vb o MainPage.xaml.cs y, a continuación ver código.

  9. Reemplace el código de MainPage.xaml.vb o MainPage.xaml.cs con el código siguiente.

    ' 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. Presione la tecla F5 para ejecutar el programa y, a continuación, elija el botón Iniciar.

Vea también

Referencia

AsTask

WhenAny

Conceptos

Programación asincrónica con Async y Await (C# y Visual Basic)

Cancelar las tareas restantes cuando se completa una (C# y Visual Basic)

Iniciar varias tareas y procesarlas a medida que se completan (C# y Visual Basic)

Otros recursos

QuickStart: mediante el operador aguardar para programación asincrónica

Cree un lector de blog

IAsyncOperationWithProgress