Pembatalan tugas

Kelas System.Threading.Tasks.Task dan System.Threading.Tasks.Task<TResult> mendukung pembatalan dengan menggunakan token pembatalan. Untuk informasi selengkapnya, lihat Pembatalan di Utas Terkelola . Di kelas Tugas, pembatalan melibatkan kerja sama antara delegasi pengguna, yang mewakili operasi yang dapat dibatalkan, dan kode yang meminta pembatalan. Pembatalan yang berhasil melibatkan kode permintaan yang memanggil metode CancellationTokenSource.Cancel dan delegasi pengguna yang mengakhiri operasi secara tepat waktu. Anda dapat mengakhiri operasi dengan menggunakan salah satu opsi berikut:

  • Dengan kembali dari delegasi. Dalam banyak skenario, opsi ini cukup. Namun, instans tugas yang dibatalkan dengan cara ini beralih ke TaskStatus.RanToCompletion status, bukan ke status TaskStatus.Canceled .

  • Dengan melemparkan OperationCanceledException dan meneruskannya token tempat pembatalan diminta. Cara yang disukai untuk melakukan adalah dengan menggunakan ThrowIfCancellationRequested metode . Tugas yang dibatalkan dengan cara ini beralih ke status Dibatalkan, yang dapat digunakan kode panggilan untuk memverifikasi bahwa tugas merespons permintaan pembatalannya.

Contoh berikut menunjukkan pola dasar untuk pembatalan tugas yang melempar pengecualian:

Catatan

Token diteruskan ke delegasi pengguna dan instans tugas.

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Run(() =>
        {
            // Were we already canceled?
            ct.ThrowIfCancellationRequested();

            bool moreToDo = true;
            while (moreToDo)
            {
                // Poll on this property if you have to do
                // other cleanup before throwing.
                if (ct.IsCancellationRequested)
                {
                    // Clean up here, then...
                    ct.ThrowIfCancellationRequested();
                }
            }
        }, tokenSource2.Token); // Pass same token to Task.Run.

        tokenSource2.Cancel();

        // Just continue on this thread, or await with try-catch:
        try
        {
            await task;
        }
        catch (OperationCanceledException e)
        {
            Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
        }
        finally
        {
            tokenSource2.Dispose();
        }

        Console.ReadKey();
    }
}
Imports System.Threading
Imports System.Threading.Tasks

Module Test
    Sub Main()
        Dim tokenSource2 As New CancellationTokenSource()
        Dim ct As CancellationToken = tokenSource2.Token

        Dim t2 = Task.Factory.StartNew(Sub()
                                           ' Were we already canceled?
                                           ct.ThrowIfCancellationRequested()

                                           Dim moreToDo As Boolean = True
                                           While moreToDo = True
                                               ' Poll on this property if you have to do
                                               ' other cleanup before throwing.
                                               If ct.IsCancellationRequested Then

                                                   ' Clean up here, then...
                                                   ct.ThrowIfCancellationRequested()
                                               End If

                                           End While
                                       End Sub _
        , tokenSource2.Token) ' Pass same token to StartNew.

        ' Cancel the task.
        tokenSource2.Cancel()

        ' Just continue on this thread, or Wait/WaitAll with try-catch:
        Try
            t2.Wait()

        Catch e As AggregateException

            For Each item In e.InnerExceptions
                Console.WriteLine(e.Message & " " & item.Message)
            Next
        Finally
            tokenSource2.Dispose()
        End Try

        Console.ReadKey()
    End Sub
End Module

Untuk contoh lengkapnya, lihat Cara: Membatalkan Tugas dan Anak-anaknya.

Ketika instans tugas mengamati yang OperationCanceledException dilemparkan oleh kode pengguna, instans tugas membandingkan token pengecualian dengan token terkait (yang diteruskan ke API yang membuat Tugas). Jika token sama dan properti token IsCancellationRequested mengembalikan true, tugas menginterpretasikannya sebagai mengakui pembatalan dan transisi ke status Dibatalkan. Jika Anda tidak menggunakan Wait metode atau WaitAll untuk menunggu tugas, maka tugas hanya mengatur statusnya ke Canceled.

Jika Anda menunggu Tugas yang beralih ke status Dibatalkan, System.Threading.Tasks.TaskCanceledException pengecualian (dibungkus dalam AggregateException pengecualian) akan dilemparkan. Pengecualian ini menunjukkan pembatalan yang berhasil alih-alih situasi yang rusak. Oleh karena itu, properti Exception tugas tersebut mengembalikan null.

Jika properti token IsCancellationRequested mengembalikan false atau jika token pengecualian tidak cocok dengan token Tugas, OperationCanceledException diperlakukan seperti pengecualian normal, menyebabkan Tugas beralih ke status Rusak. Kehadiran pengecualian lain juga akan menyebabkan Tugas beralih ke status Rusak. Anda bisa mendapatkan status tugas yang telah selesai di properti Status.

Ada kemungkinan bahwa tugas mungkin terus memproses beberapa item setelah pembatalan diminta.

Lihat juga