Zrušení úkolu

Třídy System.Threading.Tasks.Task podporují System.Threading.Tasks.Task<TResult> zrušení pomocí tokenů zrušení. Další informace naleznete v tématu Zrušení ve spravovaných vláknech. Ve třídách úloh zahrnuje zrušení spolupráci mezi delegátem uživatele, který představuje zrušitelnou operaci, a kód, který požadoval zrušení. Úspěšné zrušení zahrnuje požadavek na kód volající metodu CancellationTokenSource.Cancel a delegát uživatele ukončující operaci včas. Operace může být ukončena pomocí jedné z těchto možností:

  • Vrácením delegáta. V mnoha scénářích je tato možnost dostačující. Instance úlohy, která je tímto způsobem zrušena, ale přejde do TaskStatus.RanToCompletion stavu, nikoli do TaskStatus.Canceled stavu.

  • Vyvoláním OperationCanceledException a předáním tokenu, na kterém bylo požadováno zrušení. Upřednostňovaným způsobem, jak tuto metodu ThrowIfCancellationRequested provést, je použít. Úloha, která je tímto způsobem zrušena, přejde do zrušeného stavu, který volající kód může použít k ověření, že úloha odpověděla na žádost o zrušení.

Následující příklad ukazuje základní vzor pro zrušení úlohy, který vyvolá výjimku:

Poznámka:

Token se předá delegátu uživatele a instanci úlohy.

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

Úplný příklad najdete v tématu Postupy: Zrušení úkolu a jeho podřízených položek.

Když instance úlohy zaznamená OperationCanceledException vyvolán uživatelským kódem, porovná token výjimky s přidruženým tokenem (ten, který byl předán rozhraní API, které vytvořilo úlohu). Pokud jsou tokeny stejné a vlastnost tokenu IsCancellationRequested vrátí true, úloha to interpretuje jako potvrzení zrušení a přechody do stavu Zrušeno. Pokud k čekání na úlohu nepoužíváte metodu Wait nebo WaitAll ji nepoužíváte, nastaví úloha pouze její stav na Canceled.

Pokud čekáte na úkol, který přejde do stavu Zrušeno, System.Threading.Tasks.TaskCanceledException vyvolá se výjimka (zabalená do AggregateException výjimky). Tato výjimka značí úspěšné zrušení místo chybné situace. Proto vlastnost úkolu Exception vrátí null.

Pokud se vlastnost tokenu IsCancellationRequested vrátí false nebo pokud token výjimky neodpovídá tokenu úkolu, OperationCanceledException považuje se za normální výjimku, což způsobí, že úloha přejde do chybného stavu. Přítomnost dalších výjimek také způsobí, že úloha přejde do chybného stavu. Ve vlastnosti můžete získat stav dokončeného úkolu Status .

Je možné, že úkol může po vyžádání zrušení dál zpracovávat některé položky.

Viz také