Condividi tramite


Registrare i callback per le richieste di annullamento

Informazioni su come registrare un delegato che verrà richiamato quando una proprietà IsCancellationRequested diventa vera. Il valore passa da falso a vero quando viene eseguita una chiamata a Cancel sull'oggetto che ha creato il token. Usare questa tecnica per annullare le operazioni asincrone che non supportano in modo nativo il framework di annullamento unificato e per sbloccare i metodi che potrebbero essere in attesa del completamento di un'operazione asincrona.

Nota

Quando "Just My Code" è abilitato, Visual Studio in alcuni casi si interromperà in corrispondenza della riga che genera l'eccezione e visualizzerà un messaggio di errore simile a "Eccezione non gestita dal codice utente". Questo errore non è grave. È possibile premere F5 per continuare e osservare il comportamento di gestione delle eccezioni illustrato negli esempi seguenti. Per impedire l'interruzione di Visual Studio al primo errore, deselezionare semplicemente la casella di controllo "Just My Code" in Strumenti, Opzioni, Debug, Generale.

Esempio

Nell'esempio seguente, il metodo CancelAsync viene registrato come metodo da richiamare quando viene richiesto l'annullamento tramite il token di annullamento.

using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

class CancelWithCallback
{
    static void Main()
    {
        using var cts = new CancellationTokenSource();
        var token = cts.Token;

        _ = Task.Run(async () =>
        {
            using var client = new WebClient();

            client.DownloadStringCompleted += (_, args) =>
            {
                if (args.Cancelled)
                {
                    Console.WriteLine("The download was canceled.");
                }
                else
                {
                    Console.WriteLine("The download has completed:\n");
                    Console.WriteLine($"{args.Result}\n\nPress any key to continue.");
                }
            };

            if (!token.IsCancellationRequested)
            {
                using CancellationTokenRegistration ctr = token.Register(() => client.CancelAsync());

                Console.WriteLine("Starting request\n");
                await client.DownloadStringTaskAsync(new Uri("http://www.contoso.com"));
            }
        }, token);

        Console.WriteLine("Press 'c' to cancel.\n\n");
        if (Console.ReadKey().KeyChar == 'c')
        {
            cts.Cancel();
        }

        Console.WriteLine("\nPress any key to exit.");
        Console.ReadKey();
    }
}
Imports System.Net
Imports System.Threading

Friend Class CancelWithCallback
    Private Shared Sub Main()
        Using cts = New CancellationTokenSource()
            Dim token = cts.Token
            Task.Run(
                Async Function()
                    Using client As New WebClient()
                        AddHandler client.DownloadDataCompleted,
                        Sub(__, args)
                            If args.Cancelled Then
                                Console.WriteLine("The download was canceled.")
                            Else
                                Console.WriteLine($"The download has completed:{vbLf}")
                                Console.WriteLine($"{args.Result}{vbLf}{vbLf}Press any key to continue.")
                            End If
                        End Sub

                        If Not token.IsCancellationRequested Then
                            Dim ctr As CancellationTokenRegistration = token.Register(Sub() client.CancelAsync())
                            Console.WriteLine($"Starting request{vbLf}")
                            Await client.DownloadStringTaskAsync(New Uri("http://www.contoso.com"))
                        End If
                    End Using

                End Function, token)

            Console.WriteLine($"Press 'c' to cancel.{vbLf}{vbLf}")

            If Console.ReadKey().KeyChar = "c"c Then
                cts.Cancel()
            End If

            Console.WriteLine($"{vbLf}Press any key to exit.")
            Console.ReadKey()

        End Using
    End Sub
End Class

Se l'annullamento è già stato richiesto quando il callback viene registrato, è tuttavia garantito che il callback verrà chiamato. In questo caso particolare, il metodo CancelAsync non eseguirà alcuna operazione se nessuna operazione asincrona è in corso, quindi la chiamata al metodo è sempre sicura.

Vedi anche