Annulation des tâches

Les classes et prennent System.Threading.Tasks.Task<TResult> en charge l’annulation System.Threading.Tasks.Task à l’aide de jetons d’annulation. Pour plus d’informations, consultez Annulation dans les threads managés. Dans les classes de tâches, l’annulation implique la coopération entre le délégué de l’utilisateur, qui représente une opération annulable et le code qui a demandé l’annulation. Une annulation réussie implique la demande de code appelant la CancellationTokenSource.Cancel méthode et le délégué de l’utilisateur termine l’opération en temps opportun. Vous pouvez terminer l'opération à l'aide de l'une des options suivantes :

  • En retournant du délégué. Dans de nombreux scénarios, cette option est suffisante. Toutefois, une instance de tâche qui est annulée de cette façon passe à l’état TaskStatus.RanToCompletion , pas à l’état TaskStatus.Canceled .

  • En lève un OperationCanceledException jeton et en lui transmettant le jeton sur lequel l’annulation a été demandée. La méthode préférée consiste à utiliser la ThrowIfCancellationRequested méthode. Une tâche qui est annulée de cette façon passe à l’état annulé, que le code appelant peut utiliser pour vérifier que la tâche a répondu à sa demande d’annulation.

L’exemple suivant montre le modèle de base pour l’annulation de tâche qui lève l’exception :

Notes

Le jeton est transmis au délégué utilisateur et à l’instance de tâche.

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

Pour obtenir un exemple complet, consultez Comment : annuler une tâche et ses enfants.

Lorsqu’une instance de tâche observe une OperationCanceledException levée par le code utilisateur, elle compare le jeton de l’exception à son jeton associé (celui qui a été transmis à l’API qui a créé la tâche). Si les jetons sont identiques et que la propriété du IsCancellationRequested jeton est retournée true, la tâche l’interprète comme accusé de réception de l’annulation et des transitions vers l’état annulé. Si vous n’utilisez pas ou WaitAll si vous n’utilisez pas de Wait méthode pour attendre la tâche, la tâche définit simplement son état Canceledsur .

Si vous attendez une tâche qui passe à l’état annulé, une System.Threading.Tasks.TaskCanceledException exception (encapsulée dans une AggregateException exception) est levée. Cette exception indique une annulation réussie au lieu d’une situation défaillante. Ainsi, la propriété Exception de la tâche retourne null.

Si la propriété du IsCancellationRequested jeton retourne false ou si le jeton de l’exception ne correspond pas au jeton de la tâche, il OperationCanceledException est traité comme une exception normale, ce qui entraîne la transition de la tâche vers l’état défectueux. La présence d’autres exceptions entraîne également la transition de la tâche vers l’état défectueux. Vous pouvez obtenir l'état de la tâche terminée dans la propriété Status .

Il est possible qu’une tâche continue à traiter certains éléments après l’annulation.

Voir aussi