C#idiomatic C#
how-to-register-callbacks-for-cancellation-requestsstandard/threading

Async and concurrency

Register callbacks for cancellation requests

Learn more about: Register callbacks for cancellation requests

  • page standard/threading/how-to-register-callbacks-for-cancellation-requests
  • updated 08/14/2020

Learn how to register a delegate that will be invoked when an System.Threading.CancellationToken.IsCancellationRequested property becomes true. The value changes from false to true when a call to System.Threading.CancellationTokenSource.Cancel on the object that created the token is made. Use this technique for canceling asynchronous operations that do not natively support the unified cancellation framework, and for unblocking methods that might be waiting for an asynchronous operation to finish.

Example

In the following example, the System.Net.WebClient.CancelAsync method is registered as the method to be invoked when cancellation is requested through the cancellation token.

sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.cancellation.callback/cs/howtoexample1.cs

csharp
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();
    }
}

sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.cancellation.callback/vb/howtoexample1.vb

vb
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

If cancellation has already been requested when the callback is registered, the callback is still guaranteed to be called. In this particular case, the System.Net.WebClient.CancelAsync method will do nothing if no asynchronous operation is in progress, so it is always safe to call the method.

See also