Annulation Asynch : combler l'écart entre .NET Framework et Windows Runtime (C# et Visual Basic)

Vous pouvez optimiser vos ressources en combinant les fonctionnalités .NET Framework et Windows Runtime. L'exemple décrit dans cette rubrique vous indique comment utiliser une instance du .NET Framework CancellationToken pour ajouter un bouton d'annulation à une application qui utilise une méthode Windows Runtime pour télécharger des publications de blog sur le Web.

Notes

Pour exécuter l'exemple, Windows 8 doit être installé sur votre ordinateur.En outre, si vous souhaitez exécuter l'exemple dans Visual Studio, vous devez avoir aussi installé Visual Studio 2012, Visual Studio 2013Visual Studio Express 2012 pour Windows 8 ou Visual Studio Express 2013 pour Windows.

AsTask fournit une passerelle

Le jeton d'annulation requiert des instances Task, mais la méthode Windows Runtime produit des instances IAsyncOperationWithProgress. Vous pouvez utiliser la méthode d'extension AsTask``2 du .NET Framework pour établir une passerelle entre entre elles.

La méthode DownloadBlogsAsync dans l'exemple accomplit l'essentiel du travail.

Async Function DownloadBlogsAsync(ct As CancellationToken) As Task
    Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient()

    Dim uriList = CreateUriList()

    ' Force the SyndicationClient to download the information.
    client.BypassCacheOnRetrieve = True 


    ' The following code avoids the use of implicit typing (var) so that you  
    ' can identify the types clearly. 

    For Each uri In uriList
        ' ***These three lines are combined in the single statement that follows them. 
        'Dim feedOp As IAsyncOperationWithProgress(Of SyndicationFeed, RetrievalProgress) = 
        '    client.RetrieveFeedAsync(uri) 
        'Dim feedTask As Task(Of SyndicationFeed) = feedOp.AsTask(ct) 
        'Dim feed As SyndicationFeed = Await feedTask 

        ' ***You can combine the previous three steps in one expression. 
        Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(uri).AsTask(ct)

        DisplayResults(feed, ct)
    Next 
End Function
async Task DownloadBlogsAsync(CancellationToken ct)
{
    Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();

    var uriList = CreateUriList();

    // Force the SyndicationClient to download the information.
    client.BypassCacheOnRetrieve = true;

    // The following code avoids the use of implicit typing (var) so that you  
    // can identify the types clearly. 

    foreach (var uri in uriList)
    {
        // ***These three lines are combined in the single statement that follows them. 
        //IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> feedOp =  
        //    client.RetrieveFeedAsync(uri); 
        //Task<SyndicationFeed> feedTask = feedOp.AsTask(ct); 
        //SyndicationFeed feed = await feedTask; 

        // ***You can combine the previous three steps in one expression.
        SyndicationFeed feed = await client.RetrieveFeedAsync(uri).AsTask(ct);

        DisplayResults(feed);
    }
}

La section commentée dans la boucle détaille les étapes de transition.

  • L'appel à SyndicationClient.RetrieveFeedAsync démarre une opération asynchrone qui télécharge une publication de blog à partir d'un URI spécifié. L'opération asynchrone est une instance IAsyncOperationWithProgress.

    Dim feedOp As IAsyncOperationWithProgress(Of SyndicationFeed, RetrievalProgress) = 
        client.RetrieveFeedAsync(uri)
    
    IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> feedOp =  
        client.RetrieveFeedAsync(uri);
    
  • Étant donné que les fonctions d'annulation du .NET Framework que vous souhaitez utiliser requièrent des tâches, le code applique AsTask``1 pour représenter l'instance IAsyncOperationWithProgress en tant que Task. En particulier, le code implémente une surcharge AsTask qui accepte un argument CancellationToken.

    Dim feedTask As Task(Of SyndicationFeed) = feedOp.AsTask(ct)
    
    Task<SyndicationFeed> feedTask = feedOp.AsTask(ct);
    
  • Enfin, l'opérateur await ou Await attend que la tâche extrait le résultat SyndicationFeed.

    Dim feed As SyndicationFeed = Await feedTask
    
    SyndicationFeed feed = await feedTask;
    

Pour plus d'informations sur AsTask, consultez Extension du code de démarrage dans WhenAny : combler l'écart entre .NET Framework et Windows Runtime (C# et Visual Basic).

Points d'intérêt

Vous pouvez examiner l'exemple complet en faisant défiler l'écran jusqu'à la fin de cette rubrique, en téléchargeant l'exemple sur votre ordinateur local ou en développant l'exemple. Pour plus d'informations et d'instructions, consultez Installation de l'exemple.

En passant en revue l'exemple, vous remarquerez des astérisques qui signalent les points importants. Nous vous recommandons de lire cette section pour mieux comprendre ces points, surtout si vous n'avez pas déjà utilisé CancellationToken.

Pour implémenter un bouton Annuler, votre code doit inclure les éléments suivants.

  • Une variable CancellationTokenSource, cts, qui est dans la portée de toutes les méthodes qui y accèdent.

    Public NotInheritable Class MainPage
        Inherits Page
    
        ' ***Declare a System.Threading.CancellationTokenSource. 
        Dim cts As CancellationTokenSource
    
    public sealed partial class MainPage : Page
    {
        // ***Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;
    
  • Gestionnaire d'événements pour le bouton Annuler. Le gestionnaire d'événements utilise la méthode CancellationTokenSource.Cancel pour informer cts lorsque l'utilisateur a demandé l'annulation.

    ' ***Add an event handler for the Cancel button. 
    Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
        If cts IsNot Nothing Then
            cts.Cancel()
            ResultsTextBox.Text &= vbCrLf & "Downloads canceled by the Cancel button." 
        End If 
    End Sub
    
    // ***Add an event handler for the Cancel button. 
    private void CancelButton_Click(object sender, RoutedEventArgs e)
    {
        if (cts != null)
        {
            cts.Cancel();
            ResultsTextBox.Text += "\r\nDownloads canceled by the Cancel button.";
        }
    }
    
  • Gestionnaire d'événements pour le bouton Démarrer, StartButton_Click, qui inclut les actions suivantes.

    • Le gestionnaire d'événements instancie CancellationTokenSource, cts.

      cts = New CancellationTokenSource()
      
      // ***Instantiate the CancellationTokenSource.
      cts = new CancellationTokenSource();
      
    • Dans l'appel à DownloadBlogsAsync, qui télécharge les publications de blog, le code envoie la propriété CancellationTokenSource.Token de cts comme argument. La propriété Token propage le message si l'annulation est demandée.

      Await DownloadBlogsAsync(cts.Token)
      
      await DownloadBlogsAsync(cts.Token);
      
    • L'appel à DownloadBlogsAsync est hébergé dans une instruction try-catch qui comprend un bloc catch pour OperationCanceledException qui se produit lorsque vous cliquez sur le bouton Annuler. L'appelant de la méthode async définit l'action à effectuer. Cet exemple affiche simplement un message.

      Le code suivant illustre l'instruction try-catch complète.

      Try 
          ' ***Send a token to carry the message if cancellation is requested.
          Await DownloadBlogsAsync(cts.Token)
      
          ' ***Check for cancellations. 
      Catch op As OperationCanceledException
          ' In practice, this catch block often is empty. It is used to absorb 
          ' the exception,
          ResultsTextBox.Text &= vbCrLf & "Cancellation exception bubbles up to the caller." 
      
          ' Check for other exceptions. 
      Catch ex As Exception
          ResultsTextBox.Text =
              "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
      End Try
      
      try
      {
          // ***Send a token to carry the message if cancellation is requested.
          await DownloadBlogsAsync(cts.Token);
      }
      // ***Check for cancellations. 
      catch (OperationCanceledException)
      {
          // In practice, this catch block often is empty. It is used to absorb 
          // the exception,
          ResultsTextBox.Text += "\r\nCancellation exception bubbles up to the caller.";
      }
      // Check for other exceptions. 
      catch (Exception ex)
      {
          ResultsTextBox.Text =
              "Page could not be loaded.\r\n" + "Exception: " + ex.ToString();
      }
      
  • Comme décrit précédemment dans cette rubrique, la méthode DownloadBlogsAsync appelle la méthode Windows Runtime, RetrieveFeedAsync, et applique une méthode d'extension .NET Framework, AsTask, à l'instance IAsyncOperation retournée. AsTask représente l'instance comme une Task, afin que vous puissiez envoyer le jeton d'annulation à l'opération asynchrone. Le jeton transporte le message si vous choisissez le bouton Annuler.

    Notez qu'en utilisant AsTask, le code peut passer la même instance CancellationToken à une méthode Windows Runtime (RetrieveFeedAsync) et à une méthode .NET Framework (DownloadBlogsAsync).

    La ligne suivante montre cette partie du code.

    Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(uri).AsTask(ct)
    
    SyndicationFeed feed = await client.RetrieveFeedAsync(uri).AsTask(ct);
    
  • Si vous n'annulez pas l'application, elle produit la sortie suivante.

    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
        Windows Restart and Recovery Recipe, 3/21/2011 2:13:24 PM -07:00
    
    Extreme Windows Blog
        Samsung Series 9 27” PLS Display: Amazing Picture, 8/20/2012 2:41:48 PM -07:00
        NVIDIA GeForce GTX 660 Ti Graphics Card: Affordable Graphics Powerhouse, 8/16/2012 10:56:19 AM -07:00
        HP Z820 Workstation: Rising To the Challenge, 8/14/2012 1:57:01 PM -07:00
    
    Blogging Windows
        Windows Upgrade Offer Registration Now Available, 8/20/2012 1:01:00 PM -07:00
        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
    
    Windows for your Business
        What Windows 8 RTM Means for Businesses, 8/1/2012 9:01:00 AM -07:00
        Higher-Ed Learning with Windows 8, 7/26/2012 12:03:00 AM -07:00
        Second Public Beta of App-V 5.0 Now Available with Office Integration, 7/24/2012 10:07:26 AM -07:00
    
    Windows Experience Blog
        Tech Tuesday Live Twitter Chat with Microsoft Hardware, 8/20/2012 2:20:57 AM -07:00
        New Colors and New Artist Series Mice from Microsoft Hardware, 8/15/2012 12:06:35 AM -07:00
        Tech Tuesday Live Twitter Chat with HP on Keeping Kids Safe as They Head Back to School #winchat, 8/13/2012 12:24:18 PM -07:00
    
    Windows Security Blog
        Dealing with Fake Tech Support & Phone Scams, 6/16/2011 1:53:00 PM -07:00
        Combating social engineering tactics, like cookiejacking, to stay safer online, 5/28/2011 12:02:26 PM -07:00
        Windows 7 is now Common Criteria Certified!, 4/27/2011 9:35:01 AM -07:00
    
    Windows Home Server Blog
        Connecting Windows 8 Consumer Preview with Windows Home Server, 3/25/2012 9:06:00 AM -07:00
        Viridian PC Systems announces two new server models are available to order, 10/3/2011 12:36:00 PM -07:00
        PC Specialist to release Windows Home Server 2011, 9/27/2011 10:27:37 AM -07:00
    
    Springboard Series Blog
        Windows 8 Is Ready For Your Enterprise, 8/16/2012 9:59:00 AM -07:00
        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
    

    Si vous choisissez le bouton Annuler avant que l'application ne finisse de télécharger le contenu, le résultat ressemble à la sortie suivante.

    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
        Windows Restart and Recovery Recipe, 3/21/2011 2:13:24 PM -07:00
    
    Extreme Windows Blog
        Samsung Series 9 27” PLS Display: Amazing Picture, 8/20/2012 2:41:48 PM -07:00
        NVIDIA GeForce GTX 660 Ti Graphics Card: Affordable Graphics Powerhouse, 8/16/2012 10:56:19 AM -07:00
        HP Z820 Workstation: Rising To the Challenge, 8/14/2012 1:57:01 PM -07:00
    
    Blogging Windows
        Windows Upgrade Offer Registration Now Available, 8/20/2012 1:01:00 PM -07:00
        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
    
    Windows for your Business
        What Windows 8 RTM Means for Businesses, 8/1/2012 9:01:00 AM -07:00
        Higher-Ed Learning with Windows 8, 7/26/2012 12:03:00 AM -07:00
        Second Public Beta of App-V 5.0 Now Available with Office Integration, 7/24/2012 10:07:26 AM -07:00
    
    Downloads canceled by the Cancel button.
    Cancellation exception bubbles up to the caller.
    

Installation de l'exemple

Vous pouvez télécharger l'application, la développer vous-même ou examiner le code à la fin de cette rubrique sans l'implémenter. Visual Studio et Windows 8 doivent être installés sur votre ordinateur pour pouvoir exécuter cette application.

Pour télécharger l'application finie

  1. Téléchargez le fichier compressé depuis Exemple Async : Transition entre .NET et le runtime Windows (AsTask & Annulation).

  2. Décompressez le fichier que vous avez téléchargé, puis démarrez Visual Studio.

  3. Dans la barre de menus, sélectionnez Fichier, Ouvrir, Projet/Solution.

  4. Accédez au dossier qui contient l'exemple de code décompressé, puis ouvrez le fichier solution (.sln).

  5. Appuyez sur la touche F5 pour générer et exécuter le projet.

    Exécutez plusieurs fois le code pour vérifier que vous pouvez l'annuler à différents points.

Pour générer l'application finie

  1. Démarrez Visual Studio.

  2. Dans la barre de menus, sélectionnez Fichier, Nouveau, Projet.

    La boîte de dialogue Nouveau projet s'affiche.

  3. Dans la catégorie Installé, Modèles, choisissez Visual Basic ou Visual C#, puis Windows Store.

  4. Dans la liste des types de projet, choisissez Application vide (XAML).

  5. Nommez le projet BlogFeedWithCancellation, puis choisissez le bouton OK.

    Le nouveau projet s'affiche dans l'Explorateur de solutions.

  6. Dans l'Explorateur de solutions, ouvrez le menu contextuel de MainPage.xaml, puis choisissez Ouvrir.

  7. Dans la fenêtre XAML de MainPage.xaml, remplacez le code par le code suivant.

    <Page
        x:Class="BlogFeedWithCancellation.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:BlogFeedWithCancellation"
        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="Left" Margin="325,77,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="145" Background="#FFA89B9B" FontSize="36" Width="355"  />
            <Button x:Name="CancelButton" Content="Cancel" HorizontalAlignment="Left" Margin="684,77,0,0" VerticalAlignment="Top" Height="145" Background="#FFA89B9B" Click="CancelButton_Click" FontSize="36" Width="355"  />
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="325,222,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="711" />
        </Grid>
    </Page>
    

    Une fenêtre simple qui contient une zone de texte, un bouton de démarrage, et un bouton d'annulation apparaît dans la fenêtre Design de MainPage.xaml.

  8. Dans l'Explorateur de solutions, ouvrez le menu contextuel de MainPage.xaml.vb ou MainPage.xaml.cs, puis choisissez Afficher le Code.

  9. Remplacez le code dans MainPage.xaml.vb ou MainPage.xaml.cs par le code suivant.

    ' Add an Imports statement for SyndicationClient. 
    Imports Windows.Web.Syndication
    ' Add an Imports statement for Tasks. 
    Imports System.Threading.Tasks
    ' Add an Imports statement for CancellationToken. 
    Imports System.Threading
    
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        ' ***Declare a System.Threading.CancellationTokenSource. 
        Dim cts As CancellationTokenSource
    
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
            ResultsTextBox.Text = "" 
            ' Prevent unexpected reentrance.
            StartButton.IsEnabled = False 
    
            ' ***Instantiate the CancellationTokenSource.
            cts = New CancellationTokenSource()
    
            Try 
                ' ***Send a token to carry the message if cancellation is requested.
                Await DownloadBlogsAsync(cts.Token)
    
                ' ***Check for cancellations. 
            Catch op As OperationCanceledException
                ' In practice, this catch block often is empty. It is used to absorb 
                ' the exception,
                ResultsTextBox.Text &= vbCrLf & "Cancellation exception bubbles up to the caller." 
    
                ' Check for other exceptions. 
            Catch ex As Exception
                ResultsTextBox.Text =
                    "Page could not be loaded." & vbCrLf & "Exception: " & ex.ToString()
            End Try 
    
            ' ***Set the CancellationTokenSource to null when the work is complete.
            cts = Nothing 
    
            ' In case you want to try again.
            StartButton.IsEnabled = True 
        End Sub 
    
    
        ' Provide a parameter for the CancellationToken.
        Async Function DownloadBlogsAsync(ct As CancellationToken) As Task
            Dim client As Windows.Web.Syndication.SyndicationClient = New SyndicationClient()
    
            Dim uriList = CreateUriList()
    
            ' Force the SyndicationClient to download the information.
            client.BypassCacheOnRetrieve = True 
    
    
            ' The following code avoids the use of implicit typing (var) so that you  
            ' can identify the types clearly. 
    
            For Each uri In uriList
                ' ***These three lines are combined in the single statement that follows them. 
                'Dim feedOp As IAsyncOperationWithProgress(Of SyndicationFeed, RetrievalProgress) = 
                '    client.RetrieveFeedAsync(uri) 
                'Dim feedTask As Task(Of SyndicationFeed) = feedOp.AsTask(ct) 
                'Dim feed As SyndicationFeed = Await feedTask 
    
                ' ***You can combine the previous three steps in one expression. 
                Dim feed As SyndicationFeed = Await client.RetrieveFeedAsync(uri).AsTask(ct)
    
                DisplayResults(feed, ct)
            Next 
        End Function 
    
    
        ' ***Add an event handler for the Cancel button. 
        Private Sub cancelButton_Click(sender As Object, e As RoutedEventArgs)
            If cts IsNot Nothing Then
                cts.Cancel()
                ResultsTextBox.Text &= vbCrLf & "Downloads canceled by the Cancel button." 
            End If 
        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/business/atom.aspx"),
                        New Uri("https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx"),
                        New Uri("https://windowsteamblog.com/windows/b/windowssecurity/atom.aspx"),
                        New Uri("https://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx"),
                        New Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
                    }
            Return uriList
        End Function 
    
    
        ' You can pass the CancellationToken to this method if you think you might use a 
        ' cancellable API here in the future. 
        Sub DisplayResults(sf As SyndicationFeed, ct As CancellationToken)
            ' Title of the blog.
            ResultsTextBox.Text &= sf.Title.Text & vbCrLf
    
            ' Titles and dates for the first three blog posts. 
            For i As Integer = 0 To If(sf.Items.Count >= 3, 2, sf.Items.Count)
                ResultsTextBox.Text &= vbTab & sf.Items.ElementAt(i).Title.Text & ", " &
                        sf.Items.ElementAt(i).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 Tasks. 
    using System.Threading.Tasks;
    // Add a using directive for CancellationToken. 
    using System.Threading;
    
    
    namespace BlogFeedWithCancellation
    {
        public sealed partial class MainPage : Page
        {
            // ***Declare a System.Threading.CancellationTokenSource.
            CancellationTokenSource cts;
    
            public MainPage()
            {
                this.InitializeComponent();
            }
    
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                ResultsTextBox.Text = "";
                // Prevent unexpected reentrance.
                StartButton.IsEnabled = false;
    
                // ***Instantiate the CancellationTokenSource.
                cts = new CancellationTokenSource();
    
                try
                {
                    // ***Send a token to carry the message if cancellation is requested.
                    await DownloadBlogsAsync(cts.Token);
                }
                // ***Check for cancellations. 
                catch (OperationCanceledException)
                {
                    // In practice, this catch block often is empty. It is used to absorb 
                    // the exception,
                    ResultsTextBox.Text += "\r\nCancellation exception bubbles up to the caller.";
                }
                // Check for other exceptions. 
                catch (Exception ex)
                {
                    ResultsTextBox.Text =
                        "Page could not be loaded.\r\n" + "Exception: " + ex.ToString();
                }
    
                // ***Set the CancellationTokenSource to null when the work is complete.
                cts = null;
    
                // In case you want to try again.
                StartButton.IsEnabled = true;
            }
    
    
            // ***Provide a parameter for the CancellationToken.
            async Task DownloadBlogsAsync(CancellationToken ct)
            {
                Windows.Web.Syndication.SyndicationClient client = new SyndicationClient();
    
                var uriList = CreateUriList();
    
                // Force the SyndicationClient to download the information.
                client.BypassCacheOnRetrieve = true;
    
                // The following code avoids the use of implicit typing (var) so that you  
                // can identify the types clearly. 
    
                foreach (var uri in uriList)
                {
                    // ***These three lines are combined in the single statement that follows them. 
                    //IAsyncOperationWithProgress<SyndicationFeed, RetrievalProgress> feedOp =  
                    //    client.RetrieveFeedAsync(uri); 
                    //Task<SyndicationFeed> feedTask = feedOp.AsTask(ct); 
                    //SyndicationFeed feed = await feedTask; 
    
                    // ***You can combine the previous three steps in one expression.
                    SyndicationFeed feed = await client.RetrieveFeedAsync(uri).AsTask(ct);
    
                    DisplayResults(feed);
                }
            }
    
    
    
            // ***Add an event handler for the Cancel button. 
            private void CancelButton_Click(object sender, RoutedEventArgs e)
            {
                if (cts != null)
                {
                    cts.Cancel();
                    ResultsTextBox.Text += "\r\nDownloads canceled by the Cancel button.";
                }
            }
    
    
            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/business/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/windowsexperience/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/windowssecurity/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/windowshomeserver/atom.aspx"),
                    new Uri("https://windowsteamblog.com/windows/b/springboard/atom.aspx")
                };
                return uriList;
            }
    
    
            // You can pass the CancellationToken to this method if you think you might use a 
            // cancellable API here in the future. 
            void DisplayResults(SyndicationFeed sf)
            {
                // Title of the blog.
                ResultsTextBox.Text += sf.Title.Text + "\r\n";
    
                // Titles and dates for the first three blog posts. 
                for (int i = 0; i < (sf.Items.Count < 3 ? sf.Items.Count : 3); i++)    // Is Math.Min better?
                {
                    ResultsTextBox.Text += "\t" + sf.Items.ElementAt(i).Title.Text + ", " +
                        sf.Items.ElementAt(i).PublishedDate.ToString() + "\r\n";
                }
    
                ResultsTextBox.Text += "\r\n";
            }
        }
    }
    
  10. Choisissez la touche F5 pour exécuter le programme, puis choisissez le bouton Démarrer.

Voir aussi

Concepts

WhenAny : combler l'écart entre .NET Framework et Windows Runtime (C# et Visual Basic)

Annuler une tâche Asynch ou une liste de tâches (C# et Visual Basic)

Annuler des tâches Asynch après une période spécifique (C# et Visual Basic)

Annuler les tâches Asynch restantes lorsque l'une d'elles est terminée (C# et Visual Basic)

Jetons Cancellation