Annulation jeton dans le constructeur Tâche: pourquoi?
-
02-10-2019 - |
Question
Certains constructeurs de System.Threading.Tasks.Task
prendre un CancellationToken
comme paramètre:
CancellationTokenSource source = new CancellationTokenSource();
Task t = new Task (/* method */, source.Token);
Ce qui me déconcerte à ce sujet est qu'il n'y a aucun moyen de dans le corps de méthode pour obtenir effectivement le jeton passé dans (par exemple, rien comme Task.CurrentTask.CancellationToken
). Le jeton doit être fourni par le biais d'un autre mécanisme, tel que l'objet d'état ou capturé dans un lambda.
Dans quel but l'annulation ne fournissant jeton dans le constructeur service?
La solution
En passant ce jeton dans les associés du constructeur tâche avec cette tâche.
citant la réponse de Stephen Toub de MSDN :
Cela a deux avantages principaux:
- Si le jeton a demandé l'annulation avant la Tâche de commencer l'exécution, le Groupe ne sera pas exécuté. Plutôt que le passage à
Running
, il va immédiatement la transition versCanceled
. Cela permet d'éviter la frais de fonctionnement de la tâche si elle serait tout simplement annulé en cours d'exécution de toute façon.- Si le corps de la tâche surveille également le jeton d'annulation et jette un
OperationCanceledException
contenant ce jeton (Qui est ce queThrowIfCancellationRequested
fait), puis lorsque la tâche voit queOperationCanceledException
, il vérifie si les matchs jeton duOperationCanceledException
de la Task jeton. Dans le cas contraire, cette exception est considérée comme une reconnaissance de annulation coopérative et les transitions vers la tâche Annulée Etat (plutôt que l'état Faulted).
Autres conseils
Le constructeur utilise le jeton pour l'annulation de manutention interne. Si votre code souhaite l'accès au jeton que vous êtes responsable de le transmettre à vous-même. Je recommande vivement de lire le Programmation parallèle avec le livre Microsoft .NET à CodePlex.
Exemple d'utilisation du CTS du livre:
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task myTask = Task.Factory.StartNew(() =>
{
for (...)
{
token.ThrowIfCancellationRequested();
// Body of for loop.
}
}, token);
// ... elsewhere ...
cts.Cancel();
L'annulation est pas simple cas que beaucoup pourraient penser. Certaines des subtilités sont expliquées dans ce billet de blog sur msdn:
Par exemple:
Dans certaines situations dans les extensions parallèles et dans d'autres systèmes, il est nécessaire de se réveiller une méthode bloquée pour des raisons qui ne sont pas dus à l'annulation explicite par un utilisateur. Par exemple, si un thread est bloqué sur blockingCollection.Take () en raison de la collection étant vide et un autre thread appelle la suite blockingCollection.CompleteAdding (), le premier appel doit se réveiller et jeter un InvalidOperationException pour représenter un incorrect utilisation.
http://blogs.msdn.com /b/pfxteam/archive/2009/06/22/9791840.aspx