方法: キャンセル要求のコールバックを登録する

次の例では、トークンを作成したオブジェクトでの Cancel の呼び出しにより IsCancellationRequested プロパティが true になるときに呼び出されるデリゲートを登録する方法を示します。 この方法では、統合キャンセル フレームワークをネイティブにはサポートしない非同期操作を取り消すことができ、非同期操作の終了を待機している可能性のあるメソッドのブロックを解除できます。

メモメモ

[マイ コードのみ] が有効になっている場合、Visual Studio では、例外をスローする行で処理が中断され、"ユーザー コードで処理されない例外" に関するエラー メッセージが表示されることがあります。 このエラーは問題にはなりません。F5 キーを押して、処理が中断された箇所から続行し、以下の例に示す例外処理動作を確認できます。Visual Studio による処理が最初のエラーで中断しないようにするには、[ツール] メニューの [オプション]、[デバッグ] の順にクリックし、[全般] で [マイ コードのみ] チェック ボックスをオフにします。

使用例

次の例では、CancelAsync メソッドを、キャンセル トークンを通じてキャンセルが要求されるときに呼び出されるメソッドとして登録します。



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

コールバックを登録するときにキャンセルが既に要求されていても、コールバックは必ず呼び出されます。 このような場合、進行中の非同期操作がないと、CancelAsync メソッドは何も実行しないので、このメソッドの呼び出しは常に安全です。

参照

その他の技術情報

キャンセル