Aufgabenabbruch

Die System.Threading.Tasks.Task-Klasse und System.Threading.Tasks.Task<TResult>-Klasse unterstützen einen Abbruch durch die Verwendung von Abbruchtoken, die in .NET Framework 4 neu sind. Weitere Informationen finden Sie unter Abbruch. In den Aufgabenklassen erfordert ein Abbruch eine Zusammenarbeit zwischen dem Benutzerdelegaten, der einen abbrechbaren Vorgang darstellt, und dem Code, der den Abbruch angefordert hat. Für einen erfolgreichen Abbruch muss der anfordernde Code die CancellationTokenSource.Cancel-Methode aufrufen und der Benutzerdelegat den Vorgang rechtzeitig beenden. Sie können den Vorgang mithilfe einer dieser Optionen beenden:

  • Durch eine einfache Rückkehr vom Delegaten. In vielen Fällen reicht dies aus. Eine auf diese Weise "abgebrochene" Aufgabeninstanz geht jedoch in den Zustand RanToCompletion und nicht in den Zustand Canceled über.

  • Durch Auslösen einer OperationCanceledException und Übergeben des Tokens, für das ein Abbruch angefordert wurde. Die bevorzugte Methode hierfür ist die ThrowIfCancellationRequested-Methode. Eine auf diese Weise abgebrochene Aufgabe geht in den Zustand "Canceled" über, anhand dessen der aufrufende Code überprüfen kann, ob die Aufgabe auf seine Abbruchanforderung reagiert hat.

Im folgenden Beispiel wird das grundlegende Muster für den Aufgabenabbruch gezeigt, der die Ausnahme auslöst. Beachten Sie, dass das Token an den Benutzerdelegaten und die Aufgabeninstanz selbst übergeben wird.

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();
    }
}

Ein ausführlicheres Beispiel finden Sie unter Gewusst wie: Abbrechen einer Aufgabe und ihrer untergeordneten Elemente.

Wenn eine Aufgabeninstanz eine OperationCanceledException beobachtet, die von Benutzercode ausgelöst wurde, vergleicht sie das Token der Ausnahme mit dem zugeordneten Token (das an die API übergeben wurde, die die Aufgabe erstellt hat). Wenn diese identisch sind und die IsCancellationRequested-Eigenschaft des Tokens true zurückgibt, interpretiert die Aufgabe dies als Bestätigung des Abbruchs und geht in den Zustand Canceled über. Wenn Sie nicht mithilfe einer Wait-Methode oder WaitAll-Methode auf die Aufgabe warten, wird der Status der Aufgabe auf Canceled festgelegt.

Wenn Sie auf eine Aufgabe warten, die in den Zustand "Canceled" übergeht, wird eine TaskCanceledException (eingebunden in eine AggregateException) erzeugt und ausgelöst. Beachten Sie, dass diese Ausnahme keinen Fehler, sondern einen erfolgreichen Abbruch kennzeichnet. Daher gibt die Exception-Eigenschaft der Aufgabe NULL zurück.

Wenn die IsCancellationRequested-Eigenschaft des Tokens false zurückgibt oder das Token der Ausnahme nicht mit dem Token der Aufgabe übereinstimmt, wird die OperationCanceledException wie eine normale Ausnahme behandelt, durch die die Aufgabe in den Zustand "Faulted" übergeht. Beachten Sie weiterhin, dass die Aufgabe bei weiteren Ausnahmen ebenfalls in den Zustand "Faulted" übergeht. Sie können den Status der abgeschlossenen Aufgabe in der Status-Eigenschaft abrufen.

Es ist möglich, dass eine Aufgabe nach dem Anfordern des Abbruchs weiterhin einige Elemente verarbeitet.

Siehe auch

Aufgaben

Gewusst wie: Abbrechen einer Aufgabe und ihrer untergeordneten Elemente

Konzepte

Abbruch