Udostępnij za pośrednictwem


Rejestrowanie wywołań zwrotnych dla żądań anulowania

Dowiedz się, jak zarejestrować delegata, który zostanie wywołany, gdy IsCancellationRequested właściwość stanie się prawdziwa. Wartość zmienia się z false na true, gdy zostanie wykonane wywołanie Cancel obiektu, do którego utworzono token. Ta technika służy do anulowania operacji asynchronicznych, które nie obsługują natywnie ujednoliconej struktury anulowania, oraz do odblokowywania metod, które mogą czekać na zakończenie operacji asynchronicznej.

Uwaga

Po włączeniu opcji "Tylko mój kod" program Visual Studio w niektórych przypadkach przerwie w wierszu, który zgłasza wyjątek i wyświetla komunikat o błędzie z komunikatem "wyjątek nie jest obsługiwany przez kod użytkownika". Ten błąd jest łagodny. Możesz nacisnąć klawisz F5 , aby kontynuować działanie, i zobaczyć zachowanie obsługi wyjątków, które przedstawiono w poniższych przykładach. Aby zapobiec uszkodzeniu pierwszego błędu programu Visual Studio, usuń zaznaczenie pola wyboru "Tylko mój kod" w obszarze Narzędzia, Opcje, Debugowanie, Ogólne.

Przykład

W poniższym przykładzie metoda jest rejestrowana jako metoda, CancelAsync która ma być wywoływana po żądaniu anulowania za pośrednictwem tokenu anulowania.

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

Jeśli żądanie anulowania zostało już żądane po zarejestrowaniu wywołania zwrotnego, wywołanie zwrotne jest nadal gwarantowane. W tym konkretnym przypadku metoda nie zrobi nic, CancelAsync jeśli nie jest w toku żadna operacja asynchroniczna, więc zawsze można bezpiecznie wywołać metodę.

Zobacz też