Dela via


Aktivitetsavbokning

Klasserna System.Threading.Tasks.Task och System.Threading.Tasks.Task<TResult> stöder annullering med hjälp av annulleringstoken. Mer information finns i Annullering i hanterade trådar. I aktivitetsklasserna innebär annullering samarbete mellan användardelegaten, som representerar en avbruten åtgärd, och koden som begärde att annulleringen skulle avbrytas. En lyckad annullering innebär att den begärande koden anropar CancellationTokenSource.Cancel metoden och att användardelegaten avslutar åtgärden i tid. Du kan avsluta åtgärden med något av följande alternativ:

  • Genom att återvända från ombudet. I många scenarier räcker det här alternativet. En aktivitetsinstans som avbryts på det här sättet övergår dock till TaskStatus.RanToCompletion tillståndet, inte till tillståndet TaskStatus.Canceled .

  • Genom att kasta en OperationCanceledException och skicka den token på vilken annullering begärdes. Det bästa sättet att utföra är att använda ThrowIfCancellationRequested metoden. En uppgift som avbryts på det här sättet övergår till tillståndet Avbrytd, som den anropande koden kan använda för att verifiera att uppgiften svarade på dess annulleringsbegäran.

I följande exempel visas det grundläggande mönstret för aktivitetsavbokning som utlöser undantaget:

Kommentar

Token skickas till användardelegaten och uppgiftsinstansen.

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

Ett fullständigt exempel finns i How to: Cancel a Task and Its Children (Så här gör du: Avbryt en uppgift och dess underordnade aktiviteter).

När en aktivitetsinstans observerar en OperationCanceledException utlöses av användarkoden jämför den undantagets token med dess associerade token (den som skickades till API:et som skapade uppgiften). Om token är samma och tokens IsCancellationRequested egenskap returnerar truetolkar uppgiften detta som att bekräfta annullering och övergångar till tillståndet Avbrytd. Om du inte använder en Wait eller WaitAll -metod för att vänta på uppgiften anger aktiviteten bara dess status till Canceled.

Om du väntar på en aktivitet som övergår till tillståndet Avbrytd utlöses ett System.Threading.Tasks.TaskCanceledException undantag (omslutet i ett AggregateException undantag). Det här undantaget anger lyckad annullering i stället för en felaktig situation. Därför returnerar nullaktivitetens Exception egenskap .

Om tokens IsCancellationRequested egenskap returnerar false eller om undantagets token inte matchar aktivitetens token behandlas den OperationCanceledException som ett normalt undantag, vilket gör att aktiviteten övergår till feltillståndet. Förekomsten av andra undantag gör också att aktiviteten övergår till feltillståndet. Du kan hämta status för den slutförda aktiviteten i egenskapen Status .

Det är möjligt att en uppgift kan fortsätta att bearbeta vissa objekt när annulleringen har begärts.

Se även