Zrušení úlohyTask Cancellation

Třídy System.Threading.Tasks.Task a System.Threading.Tasks.Task<TResult> podporují zrušení pomocí tokenů zrušení v .NET Framework.The System.Threading.Tasks.Task and System.Threading.Tasks.Task<TResult> classes support cancellation through the use of cancellation tokens in the .NET Framework. Další informace naleznete v tématu zrušení ve spravovaných vláknech.For more information, see Cancellation in Managed Threads. Ve třídách úloh zahrnuje zrušení spolupráci mezi uživatelským delegátem, který představuje zrušitelnou operaci, a kódem, který požaduje zrušení.In the Task classes, cancellation involves cooperation between the user delegate, which represents a cancelable operation and the code that requested the cancellation. Úspěšné zrušení zahrnuje požadováný kód volající metodu CancellationTokenSource.Cancel a uživatelský delegát ukončí operaci včas.A successful cancellation involves the requesting code calling the CancellationTokenSource.Cancel method, and the user delegate terminating the operation in a timely manner. Operace může být ukončena pomocí jedné z těchto možností:You can terminate the operation by using one of these options:

  • Jednoduše vrácením z delegáta.By simply returning from the delegate. V mnoha scénářích to stačí; instance úlohy, která je tímto způsobem zrušena, však přechází do stavu TaskStatus.RanToCompletion, nikoli do stavu TaskStatus.Canceled.In many scenarios this is sufficient; however, a task instance that is canceled in this way transitions to the TaskStatus.RanToCompletion state, not to the TaskStatus.Canceled state.

  • Vyvoláním OperationCanceledException a předáním tokenu, na kterém bylo zrušení požadováno.By throwing a OperationCanceledException and passing it the token on which cancellation was requested. Upřednostňovaným způsobem, jak to provést, je použít metodu ThrowIfCancellationRequested.The preferred way to do this is to use the ThrowIfCancellationRequested method. Úloha, která je zrušena tímto způsobem, přechází do stavu Zrušeno, který může volající kód použít k ověření, zda úloha odpověděla na jeho žádost o zrušení.A task that is canceled in this way transitions to the Canceled state, which the calling code can use to verify that the task responded to its cancellation request.

Následující příklad zobrazuje základní vzor pro zrušení úlohy, který vyvolává výjimku.The following example shows the basic pattern for task cancellation that throws the exception. Token je předán uživatelskému delegátu a samotné instanci úlohy.Note that the token is passed to the user delegate and to the task instance itself.

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ější příklad naleznete v tématu How to: Cancel a a jejích podřízených.For a more complete example, see How to: Cancel a Task and Its Children.

Když instance úlohy sleduje OperationCanceledException vyvolanou uživatelským kódem, porovná token výjimky s jeho přidruženým tokenem (ten, který byl předán rozhraní API, které vytvořilo úlohu).When a task instance observes an OperationCanceledException thrown by user code, it compares the exception's token to its associated token (the one that was passed to the API that created the Task). Pokud jsou stejné a vlastnost IsCancellationRequested tokenu vrátí hodnotu true, úloha je interpretuje jako potvrzení zrušení a přechodů do zrušeného stavu.If they are the same and the token's IsCancellationRequested property returns true, the task interprets this as acknowledging cancellation and transitions to the Canceled state. Pokud nepoužijete metodu Wait nebo WaitAll k čekání na úlohu, pak tato úloha nastaví stav na Canceled.If you do not use a Wait or WaitAll method to wait for the task, then the task just sets its status to Canceled.

Pokud čekáte na úlohu, která přechází do stavu Canceled, je vyvolána výjimka System.Threading.Tasks.TaskCanceledException (zabalené v AggregateException výjimce).If you are waiting on a Task that transitions to the Canceled state, a System.Threading.Tasks.TaskCanceledException exception (wrapped in an AggregateException exception) is thrown. Všimněte si, že tato výjimka označuje úspěšné zrušení namísto poruchové situace.Note that this exception indicates successful cancellation instead of a faulty situation. Proto vlastnost Exception úlohy vrátí null.Therefore, the task's Exception property returns null.

Vrátí-li vlastnost IsCancellationRequested tokenu hodnotu false nebo pokud token výjimky neodpovídá tokenu úkolu, OperationCanceledException je považován za normální výjimku, což způsobí, že se úkol převede do stavu Faulted.If the token's IsCancellationRequested property returns false or if the exception's token does not match the Task's token, the OperationCanceledException is treated like a normal exception, causing the Task to transition to the Faulted state. Přítomnost dalších výjimek rovněž způsobí, že úloha přejde do stavu Chyba.Also note that the presence of other exceptions will also cause the Task to transition to the Faulted state. Stav dokončené úlohy můžete získat ve vlastnosti Status.You can get the status of the completed task in the Status property.

Je možné, že úloha bude pokračovat ve zpracování některých položek poté, co bylo požádáno o zrušení.It is possible that a task may continue to process some items after cancellation is requested.

Viz také:See also