취소 요청에 대한 콜백 등록Register callbacks for cancellation requests

IsCancellationRequested 속성이 true가 될 때 호출되는 대리자를 등록하는 방법을 알아봅니다.Learn how to register a delegate that will be invoked when a IsCancellationRequested property becomes true. 토큰을 만든 개체에서 Cancel을 호출하면 값이 false에서 true로 변경됩니다.The value changes from false to true when a call to 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.

참고

“내 코드만”이 사용하도록 설정된 경우 Visual Studio가 예외를 발생시키는 줄에서 중단하고 "예외가 사용자 코드에서 처리되지 않았다"는 오류 메시지를 표시합니다.When "Just My Code" is enabled, Visual Studio in some cases will break on the line that throws the exception and display an error message that says "exception not handled by user code." 이 오류는 심각하지는 않습니다.This error is benign. F5 키를 눌러 해당 지점부터 계속하고 아래 예제에 설명된 예외 처리 동작을 확인할 수 있습니다.You can press F5 to continue from it, and see the exception-handling behavior that is demonstrated in the examples below. 첫 번째 오류 지점에서 Visual Studio가 실행을 중단하지 않도록 하려면 도구, 옵션, 디버깅, 일반 을 차례로 선택하고 “내 코드만” 확인란의 선택을 취소하기만 하면 됩니다.To prevent Visual Studio from breaking on the first error, just uncheck the "Just My Code" checkbox under Tools, Options, Debugging, General.

예제Example

다음 예제에서 CancelAsync 메서드는 취소 토큰을 통해 취소가 요청될 때 호출할 메서드로 등록됩니다.In the following example, the CancelAsync method is registered as the method to be invoked when cancellation is requested through the cancellation token.

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

콜백을 등록할 때 이미 취소가 요청된 경우에도 콜백 호출이 보장됩니다.If cancellation has already been requested when the callback is registered, the callback is still guaranteed to be called. 이 특별한 경우에서는 진행 중인 비동기 작업이 없는 경우 CancelAsync 메서드가 아무 작업도 하지 않으므로 항상 안전하게 메서드를 호출할 수 있습니다.In this particular case, the CancelAsync method will do nothing if no asynchronous operation is in progress, so it is always safe to call the method.

참고 항목See also