Partager via


Comment : enregistrer des rappels pour les demandes d'annulation

L'exemple suivant montre comment inscrire un délégué qui sera appelé lorsqu'une propriété IsCancellationRequested prendra la valeur true en raison d'un appel à Cancel sur l'objet qui a créé le jeton. Utilisez cette technique pour l'annulation des opérations asynchrones qui ne prennent pas en charge l'infrastructure d'annulation unifiée en mode natif, ainsi que pour le déblocage des méthodes qui attendent éventuellement l'achèvement d'une opération asynchrone.

RemarqueRemarque

Lorsque l'option "Uniquement mon code" est activée, Visual Studio s'arrête dans certains cas sur la ligne qui lève l'exception et affiche un message d'erreur indiquant que l'exception n'est pas gérée par le code utilisateur. Cette erreur est bénigne.Vous pouvez appuyer sur F5 pour continuer et voir le comportement de gestion des exceptions illustré dans les exemples ci-dessous.Pour empêcher Visual Studio de s'arrêter sur la première erreur, il vous suffit de désactiver la case à cocher "Uniquement mon code" sous Outils, Options, Débogage, Général.

Exemple

Dans l'exemple suivant, la méthode CancelAsync est inscrite comme méthode à appeler lorsque l'annulation est demandée via le jeton d'annulation.



Class CancelWithCallback


    Shared Sub Main()

        Dim cts As New CancellationTokenSource()

        ' Start cancelable task.
        Dim t As Task = Task.Factory.StartNew(Sub() DoWork(cts.Token))

        Console.WriteLine("Press 'c' to cancel.")
        Dim ch As Char = Console.ReadKey().KeyChar
        If ch = "c"c Then

            cts.Cancel()
        End If
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub

    Shared Sub DoWork(ByVal token As CancellationToken)

        Dim wc As New WebClient()

        ' Create an event handler to receive the result.
        AddHandler wc.DownloadStringCompleted, Sub(obj, e)

                                                   ' Checks status of WebClient, not external token
                                                   If e.Cancelled = False Then

                                                       Console.WriteLine(e.Result + "\r\nPress any key.")

                                                   Else
                                                       Console.WriteLine("Download was canceled.")
                                                   End If
                                               End Sub

        token.Register(Sub() wc.CancelAsync())

        Console.WriteLine("Starting request")
        wc.DownloadStringAsync(New Uri("https://www.contoso.com"))
    End Sub
End Class
namespace Cancel3
{
    using System;
    using System.Net;
    using System.Threading;
    using System.Threading.Tasks;

    class CancelWithCallback
    {

        static void Main(string[] args)
        {
            var cts = new CancellationTokenSource();

            // Start cancelable task.
            Task t = Task.Factory.StartNew(() =>
            {
                DoWork(cts.Token);
            });

            Console.WriteLine("Press 'c' to cancel.");
            char ch = Console.ReadKey().KeyChar;
            if (ch == 'c')
            {
                cts.Cancel();
            }
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }

        static void DoWork(CancellationToken token)
        {
            WebClient wc = new WebClient();

            // Create an event handler to receive the result.
            wc.DownloadStringCompleted += (obj, e) =>
            {
                // Checks status of WebClient, not external token
                if (!e.Cancelled)
                {
                    Console.WriteLine(e.Result + "\r\nPress any key.");
                }
                else
                    Console.WriteLine("Download was canceled.");
            };

            // Do not initiate download if the external token
            // has already been canceled.
            if (!token.IsCancellationRequested)
            {
                // Register the callback to a method that can unblock.
                // Dispose of the CancellationTokenRegistration object
                // after the callback has completed.
                using (CancellationTokenRegistration ctr = token.Register(() => wc.CancelAsync()))
                {
                    Console.WriteLine("Starting request");
                    wc.DownloadStringAsync(new Uri("https://www.contoso.com"));
                }
            }
        }
    }
}

Si l'annulation a déjà été demandée lors de l'inscription du rappel, le rappel est toujours effectué. Dans ce cas particulier, la méthode CancelAsync ne fera rien si aucune opération asynchrone n'est en cours, afin que l'appel à la méthode soit toujours sécurisé.

Voir aussi

Concepts

Annulation