157 votes

Comment utiliser le CancellationToken propriété?

Par rapport au code précédent pour la classe RulyCanceler, je voulais exécuter du code à l'aide de CancellationTokenSource.

Comment puis-je l'utiliser comme mentionné dans l'Annulation des Jetons, c'est à dire sans lancer/attraper une exception? Puis-je utiliser l' IsCancellationRequested de la propriété?

J'ai tenté de l'utiliser comme ceci:

cancelToken.ThrowIfCancellationRequested();

et

try
{
  new Thread(() => Work(cancelSource.Token)).Start();
}
catch (OperationCanceledException)
{
  Console.WriteLine("Canceled!");
}

mais cela a donné une erreur d'exécution sur cancelToken.ThrowIfCancellationRequested(); méthode Work(CancellationToken cancelToken):

System.OperationCanceledException was unhandled
  Message=The operation was canceled.
  Source=mscorlib
  StackTrace:
       at System.Threading.CancellationToken.ThrowIfCancellationRequested()
       at _7CancellationTokens.Token.Work(CancellationToken cancelToken) in C:\xxx\Token.cs:line 33
       at _7CancellationTokens.Token.<>c__DisplayClass1.<Main>b__0() in C:\xxx\Token.cs:line 22
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

Le code que j'ai réussi a couru pris la OperationCanceledException dans le nouveau thread:

using System;
using System.Threading;
namespace _7CancellationTokens
{
  internal class Token
  {
    private static void Main()
    {
      var cancelSource = new CancellationTokenSource();
      new Thread(() =>
      {
         try
         {
           Work(cancelSource.Token); //).Start();
         }
         catch (OperationCanceledException)
         {
            Console.WriteLine("Canceled!");
         }
         }).Start();

      Thread.Sleep(1000);
      cancelSource.Cancel(); // Safely cancel worker.
      Console.ReadLine();
    }
    private static void Work(CancellationToken cancelToken)
    {
      while (true)
      {
        Console.Write("345");
        cancelToken.ThrowIfCancellationRequested();
      }
    }
  }
}

185voto

Oleksandr Pshenychnyy Points 3177

Vous pouvez mettre en œuvre votre méthode de travail comme suit:

private static void Work(CancellationToken cancelToken)
{
    while (true)
    {
        if(cancelToken.IsCancellationRequested)
        {
            return;
        }
        Console.Write("345");
    }
}

C'est tout. Vous avez toujours besoin de gérer l'annulation par vous-même - la sortie de la méthode quand il est approprié de temps à sortir (de sorte que votre travail et vos données sont en état cohérent)

Mise à JOUR: je préfère ne pas écrire while (!cancelToken.IsCancellationRequested) parce que souvent il y a peu de points de sortie où vous pouvez vous arrêter l'exécution en toute sécurité à travers le corps de boucle, et en boucle ont généralement une condition logique de sortie (itérer sur tous les éléments de la collection etc.). Donc, je pense qu'il est préférable de ne pas mélanger les conditions qu'ils ont l'intention différente.

24voto

user3285954 Points 149

@BrainSlugs83

Vous ne devriez pas aveuglément confiance à tout le posté sur stackoverflow. Le commentaire de Jens code est incorrect, le paramètre n'est pas de contrôler si des exceptions sont levées ou pas.

MSDN est très clair ce que les commandes de paramètre, l'avez-vous lu? http://msdn.microsoft.com/en-us/library/dd321703(v=vs. 110).aspx

Si throwOnFirstException est vrai, une exception sera immédiatement propager hors de l'appel, d'Annuler, de prévenir le reste des rappels et annulables les opérations en cours de traitement. Si throwOnFirstException est faux, cette surcharge agrège toutes les exceptions levées dans un AggregateException, telles que l'un rappel de lancer une exception n'empêchera pas d'autres rappels enregistrés d'être exécutée.

Le nom de la variable est également mal en raison d'Annuler est appelée sur CancellationTokenSource pas le jeton lui-même et la source des changements de l'état de chaque jeton qu'il gère.

17voto

Jens Kloster Points 3974

Vous pouvez l'utiliser comme ceci:

  var cancelToken = new CancellationTokenSource();
  Task.Factory.StartNew(() => DoEthernalWork(), cancelToken.Token);

  Thread.Sleep(1000); //simulate some other work

  //this stops the Task:
  cancelToken.Cancel(false); //false indicates that no exceptions will be thrown.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X