Bagikan melalui


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. Dalam 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 CancellationTokenSource.Cancel metode dan pengguna mendelegasikan penghentian operasi secara tepat waktu. Anda dapat mengakhiri operasi dengan menggunakan salah satu opsi berikut:

  • Dengan kembali dari tugas 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 kepada token di mana pembatalan diminta. Cara yang disukai untuk melakukan adalah dengan menggunakan metode ThrowIfCancellationRequested. 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 menghasilkan pengecualian.

Nota

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 Subtugasnya.

Ketika instans tugas mengamati pengecualian OperationCanceledException yang dilemparkan oleh kode pengguna, instans tersebut 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 Task yang beralih ke status Dibatalkan, System.Threading.Tasks.TaskCanceledException pengecualian (dibungkus dalam AggregateException pengecualian) akan dilemparkan. Pengecualian ini menunjukkan pembatalan yang berhasil daripada keadaan yang bermasalah. Oleh karena itu, properti tugas Exception 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 Kesalahan. Anda dapat memeriksa status tugas yang telah selesai pada properti Status.

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

Lihat juga