Sdílet prostřednictvím


Zrušení úlohy

Třídy System.Threading.Tasks.Task a System.Threading.Tasks.Task<TResult> podporují zrušení prostřednictvím použití tokenů zrušení, které jsou nově v .NET Framework 4. Další informace naleznete v tématu Zrušení. Ve třídách Task zrušení zahrnuje spolupráci mezi uživatelským delegátem, který představuje zrušitelnou operaci, a kódem, který požaduje zrušení. Úspěšné zrušení zahrnuje volání metody CancellationTokenSource.Cancel žádajícím kódem a ukončení činnosti uživatelského delegáta v časovém limitu. Operace můžete být ukončena pomocí jedné z těchto možností:

  • Jednoduše vrácením z delegáta. V mnoha případech to je dostatečná; úkol však instance, který je "zrušena" Tímto způsobem přechody na RanToCompletion státu, stav zrušeno.

  • Po vyvolání výjimky OperationCanceledException a předání tokenu, na který bylo zrušení požadováno. Upřednostňovaným způsobem je použít k tomuto metodu ThrowIfCancellationRequested. Úloha, která je zrušena tímto způsobem přechází do stavu Canceled, který může volající kód použít k ověření, že úloha odpověděla na jeho žádost o zrušení.

Následující příklad zobrazuje základní vzor pro zrušení úlohy, které vyvolává výjimku. Všimněte si, že token je předán uživatelskému delegátovi a samotné instanci úlohy.

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
        End Try

        Console.ReadKey()
    End Sub
End Module
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
    static void Main()
    {

        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Factory.StartNew(() =>
        {

            // 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 StartNew.

        tokenSource2.Cancel();

        // Just continue on this thread, or Wait/WaitAll with try-catch:
        try
        {
            task.Wait();
        }
        catch (AggregateException e)
        {
            foreach (var v in e.InnerExceptions)
                Console.WriteLine(e.Message + " " + v.Message);
        }

        Console.ReadKey();
    }
}

Kompletní příklad naleznete v Postupy: Zrušit úlohy a její děti.

Když instance úlohy spatří výjimku OperationCanceledException vyvolanou v uživatelském kódu, porovná token této výjimky se svým přiřazeným tokenem (ten, který byl předán rozhraní API, které vytvořilo úlohu). Jestliže jsou stejné a tokenu IsCancellationRequested Vlastnost vrací hodnotu true, úkol interpretuje jako UZNÁVAJÍCE zrušení a přechody do stavu zrušeno. Pokud nepoužíváte Wait nebo WaitAll Metoda čekat úkol, pak úkol pouze nastaví svůj stav na Canceled.

Pokud čekáte na úlohu přecházející do stavu Canceled, je vytvořena a vyvolána výjimka TaskCanceledException (obalena do AggregateException). Všimněte si, že tato výjimka označuje úspěšné zrušení namísto poruchové situace. Vlastnost Exception třídy Task proto vrátí null.

Pokud vlastnost IsCancellationRequested tokenu vrátí false nebo pokud token výjimky neodpovídá tokenu úlohy, s výjimkou OperationCanceledException se zachází stejně jako s normální výjimkou, což znamená přechod úlohy do stavu Faulted. Také je třeba poznamenat, že přítomnost dalších výjimek rovněž způsobí, že úloha přejde do stavu Faulted. Stav dokončené úlohy lze získat z vlastnosti Status.

Je možné, že úloha bude pokračovat ve zpracování některých položek poté, co je požádáno o zrušení.

Viz také

Úkoly

Postupy: Zrušit úlohy a její děti

Koncepty

Zrušení