169 votes

Pourquoi CancellationToken est-il séparé d'AnnulationTokenSource?

Je suis à la recherche d'une justification de la raison .NET a CancellationToken struct en plus de CancellationTokenSource classe. Je comprends comment l'API est utilisée, mais qui veulent aussi comprendre pourquoi il est conçu de cette façon.

I. e., pourquoi devons-nous:

var cts = new CancellationTokenSource();
SomeCancellableOperation(cts.Token);

...
public void SomeCancellableOperation(CancellationToken token) {
    ...
    token.ThrowIfCancellationRequested();
    ...
}

au lieu de directement passer CancellationTokenSource autour comme:

var cts = new CancellationTokenSource();
SomeCancellableOperation(cts);

...
public void SomeCancellableOperation(CancellationTokenSource cts) {
    ...
    cts.ThrowIfCancellationRequested();
    ...
}

Est-ce une optimisation de la performance basée sur le fait que l'annulation de contrôles d'état de se produire plus souvent que de passer le jeton?

De sorte que CancellationTokenSource pouvez garder une trace de et mise à jour CancellationTokens, et pour chaque jeton de l'annulation d'un local d'accès sur le terrain?

Étant donné qu'un volatile bool avec aucun verrouillage n'est suffisante dans les deux cas, je ne vois toujours pas pourquoi ce serait plus rapide.

Merci!

159voto

J'ai été impliqué dans la conception et la mise en œuvre de ces classes.

La réponse courte est "la séparation des préoccupations". Il est vrai qu'il y a de diverses stratégies de mise en œuvre et que certaines sont plus simples au moins en ce qui concerne le type de système et d'apprentissage initiale. Cependant, la CTS et la TDM sont prévus pour une utilisation dans un grand nombre de scénarios (comme la profondeur de la bibliothèque de piles, calcul parallèle, async, etc) et donc a été conçu avec de nombreux complexes de cas d'utilisation à l'esprit. C'est un dessin destiné à encourager le succès de motifs et de décourager les anti-modèles sans sacrifier les performances.

Si la porte a été laissée ouverte pour virer les Api, alors l'utilité de l'annulation de la conception pourrait rapidement s'éroder.

107voto

SolutionYogi Points 16697

J'ai eu exactement la même question que vous et j'ai voulu comprendre la logique de cette conception.

La accepté de répondre à eu la justification exactement. Voici la confirmation de la part de l'équipe qui a conçu cette fonction (l'emphase est mienne):

Deux nouveaux types de former la base du cadre: Un CancellationToken est une structure qui représente un potentiel de demande d'annulation". Cette struct est passé dans les appels de méthode en tant que paramètre et la méthode peut sondage sur elle ou d'enregistrer un rappel pour être déclenché lorsque l'annulation est demandé. Une CancellationTokenSource est une classe qui fournit l' mécanisme pour initier une demande d'annulation et il a un Jeton propriété pour l'obtention d'un jeton associé. Il aurait été naturel pour combiner ces deux classes en une seule, mais cette conception permet d'avoir les deux les principales opérations (mise en fonction d'une requête en annulation contre l'observation et répondre à annulation) pour être clairement séparées. En particulier, des méthodes qui prennent seulement un CancellationToken peut observer une annulation demande mais ne peut pas lancer une.

Lien: .NET 4 Annulation Cadre

À mon avis, le fait que CancellationToken ne peut que constater l'état et de ne pas la changer, est extrêmement critique. Vous pouvez remettre le jeton comme des bonbons et ne jamais s'inquiéter que quelqu'un d'autre que vous, vous l'Annuler. Il vous protège contre les hostiles de la troisième partie du code. Oui, les chances sont minces, mais personnellement, je voudrais que garantie.

J'ai aussi l'impression qu'il fait de l'API propre et évite accidentelle erreur et favorise une meilleure conception de composant.

Regardons API publique pour ces deux classes.

CancellationToken API

CancellationTokenSource API

Si vous étiez à les combiner, quand je suis en train d'écrire mon LongRunningFunction, je vais voir des méthodes semblables à celles de plusieurs surcharges de la "Annuler" qui je ne devrais pas être en utilisant. Personnellement, j'ai hate de voir la méthode dispose.

Je pense que la classe en cours de conception suit la fosse de la réussite de la philosophie, il guide les développeurs à créer de meilleurs composants qui peuvent gérer l'annulation de Tâches, puis instrument ensemble dans de nombreuses façon de créer des flux de travail complexes.

Permettez-moi de vous poser une question, avez-vous demandé quel est le but de jeton.Inscrire? Elle n'a pas de sens pour moi. Et puis j'ai lu l'Annulation dans la gestion des Threads et tout est devenu limpide.

Je crois que l'Annulation Cadre de la Conception dans le TPL est absolument parfait.

66voto

Cory Nelson Points 10540

Ils sont séparés non pas pour des raisons techniques, mais sémantique. Si vous regardez à la mise en œuvre de l' CancellationToken sous ILSpy, vous trouverez que c'est simplement un wrapper autour de CancellationTokenSource (et donc pas différents en terme de performance que de passer autour d'une référence).

Ils fournissent à cette séparation de la fonctionnalité pour rendre les choses plus prévisible: quand vous passez une méthode, d'une CancellationToken, vous savez que vous êtes toujours le seul qui peut l'annuler. Bien sûr, la méthode pourrait toujours jeter un TaskCancelledException, mais l' CancellationToken elle-même, et toutes les autres méthodes de référencement, même -- serait de rester en sécurité.

11voto

Erno de Weerd Points 30391

CancellationToken est une structure dans laquelle de nombreuses copies peuvent exister en raison de sa transmission aux méthodes.

CancellationTokenSource définit l'état de TOUTES les copies d'un jeton lors de l'appel de Cancel sur la source. Voir cette page MSDN

La raison de la conception pourrait être juste une question de séparation des préoccupations et de la rapidité d'une structure.

2voto

n8wrl Points 12485

Le CancellationTokenSource est la "chose" que les questions de l'annulation, pour quelque raison que ce soit. Il a besoin d'une façon "d'expédition" que l'annulation de tous les CancellationToken est qu'il a émises. C'est ainsi que, par exemple, ASP.NET peut annuler les opérations lorsqu'une demande est annulée. Chaque demande a un CTSource qui transmet l'annulation de tous les jetons qu'il a émises.

Cette grande pour les tests unitaires BTW - créez votre propre source de jeton d'annulation, obtenir un jeton, d'appel d'Annuler le soource, et passe le jeton à votre code pour gérer l'annulation.

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