Annulation d’une tâche

J’ai essayé d’exécuter un exemple simple sur l’annulation d’une tâche comme celle ci-dessous.

CancellationTokenSource tokenSource2 = new CancellationTokenSource(); CancellationToken token2 = tokenSource2.Token; Task task2 = new Task(() => { for (int i = 0; i < int.MaxValue; i++) { token2.ThrowIfCancellationRequested(); Thread.Sleep(100); Console.WriteLine("Task 2 - Int value {0}", i); } }, token2); task2.Start(); Console.WriteLine("Press any key to cancel the task"); Console.ReadLine(); tokenSource2.Cancel(); Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled); 

Je m’attendais à ce que Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled); serait imprimer **"Task 2 cancelled? True"** , mais il a imprimé “Faux” .

Sais tu ce qu’il s’est passé? Est-ce le comportement attendu? Merci.

EDIT: pour s’assurer que la tâche n’est pas terminée avant l’appel de la demande d’annulation. J’ai ajouté le Console.ReadLine() .

Premièrement, vous comprenez peut-être mal ce IsCanceled signifie IsCanceled ? Cela ne signifie pas que “cette Task est en attente d’annulation, elle devrait donc s’achever sous peu”, cela signifie que “cette Task a été annulée, elle est maintenant terminée”.

Si vous ne comprenez pas mal cela, réfléchissez à la séquence exacte des événements. Qu’est-ce qui se passe est la suivante:

  1. ThrowIfCancellationRequested() est appelée, mais le jeton n’a pas encore été annulé, il n’est donc pas lancé.
  2. Thread.Sleep() est appelé, ainsi le thread qui exécute la Task veille.
  3. Cancel() est appelé.
  4. IsCanceled est cochée. Le code de la Task n’a pas pu se rendre compte que le jeton a été annulé. Il est donc toujours en cours d’exécution. IsCanceled renvoie donc la IsCanceled false .
  5. ThrowIfCancellationRequested() est appelé à nouveau, cette fois, il jette, ce qui annule réellement la Task .

C’est pourquoi ISCanceled false . Si vous souhaitez qu’elle renvoie la valeur true , vous pouvez append quelque chose comme Thread.Sleep(150) avant de vérifier IsCanceled ou, mieux encore, d’attendre la fin de la Task .

La tâche est terminée avant que vous appeliez pour une annulation, jetez un œil à ce qui suit ci-dessous. Cela peut aider à éclaircir la façon dont vous résolvez votre problème.

En lisant ici http://social.msdn.microsoft.com/Forums/da-DK/parallelextensions/thread/9f88132a-f8bd-4885-ab63-645d7b6c2127, il semble que le jeton est utilisé pour annuler la tâche AVANT que la tâche soit “vraiment” a commencé, mais après il a été mis en queue.

Il s’agit davantage d’un moyen d’annuler une tâche planifiée mais non encore démarrée. Une fois que la tâche est en cours d’exécution, le seul moyen de l’annuler est de coopérer via votre propre vérification au sein de la méthode. Sans cela, vous devez toujours démarrer la tâche, puis la vérifier en interne, ce qui appendait beaucoup de temps supplémentaire inutile.

Vous pouvez même le lire à partir du jeton d’annulation dans le constructeur de tâches: pourquoi?

Ce n’est pas une réponse mais c’est trop long pour écrire dans un commentaire

 CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = cancellationTokenSource.Token; Task task = new Task(() => { for (int i = 0; i < int.MaxValue; i++) { cancellationToken.ThrowIfCancellationRequested(); Console.WriteLine("Task 2 - Int value {0}", i); } }, cancellationToken); task.Start(); cancellationTokenSource.Cancel(); try { task.Wait(); } catch (AggregateException ae) { if(ae.InnerExceptions.Single() is TaskCanceledException) Console.WriteLine("Caught TaskCanceledException"); else Console.WriteLine("Did not catch canceled"); } Console.WriteLine("Task 2 cancelled? {0}", task.IsCanceled); 
  • Le code ci-dessus imprime ce qui est attendu et je n'ai jamais eu l'empreinte de 'Task 2 - Int value {0}'. Je ne pense donc pas que cela se soit terminé avant d'annuler.
  • Notez que l'annulation de la tâche génère une exception dans mon exemple.
  • Certains patterns for handling exceptions using tasks peuvent être intéressants à lire.