Como: Registrar retornos de chamada para solicitações de cancelamento

O exemplo a seguir mostra como registrar um delegado que será chamado quando uma IsCancellationRequested a propriedade se torna true devido a uma chamada para Cancel no objeto que criou o token. Use essa técnica para cancelar operações assíncronas que não suportam a estrutura unificada de cancelamento nativamente e para os métodos de desbloqueio podem estar aguardando uma operação assíncrona concluir.

Observação

Quando "apenas meu código" é ativado, Visual Studio em alguns casos será quebrar na linha que lança a exceção e exibirá uma mensagem de erro que diz "exceção não tratada pelo código do usuário". Este erro é benigno.Pressione F5 para continuar a partir dele e ver o comportamento de manipulação de exceção é demonstrado nos exemplos abaixo.Para evitar que Visual Studio no primeiro erro, basta desmarcar o "Just My Code" caixa de seleção em Ferramentas, opções, depuração, geral.

Exemplo

No exemplo a seguir, o CancelAsync método está registrado como o método seja chamado quando o cancelamento for solicitado por meio do token de cancelamento.



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"));
                }
            }
        }
    }
}

Se já tiver sido solicitado o cancelamento quando o retorno de chamada é registrado, ainda é garantido que o retorno de chamada ser chamado. Nesse caso específico, o CancelAsync método não fará nada se nenhuma operação assíncrona está em andamento, portanto, é sempre seguro chamar o método.

Consulte também

Conceitos

Cancelamento