Je viens de commencer à jouer avec async / wait dans .Net 4.5. Une chose qui m'intéresse au départ, pourquoi le mot-clé async est-il nécessaire? L'explication que j'ai lue était que c'est un marqueur, donc le compilateur sait qu'une méthode attend quelque chose. Mais il semble que le compilateur devrait être capable de comprendre cela sans mot-clé. Que fait-il d'autre?
19
Réponses:
Il y a plusieurs réponses ici, et toutes parlent de ce que font les méthodes asynchrones, mais aucune ne répond à la question, c'est pourquoi
async
est nécessaire en tant que mot-clé qui va dans la déclaration de fonction.Ce n'est pas "de demander au compilateur de transformer la fonction d'une manière spéciale";
await
seul pouvait le faire. Pourquoi? Parce que C # a déjà un autre mécanisme où la présence d'un mot - clé spécial dans le corps de méthode provoque le compilateur pour effectuer extrême (et très similaire àasync/await
) des transformations sur le corps de la méthode:yield
.Sauf que ce
yield
n'est pas son propre mot-clé en C #, et comprendre pourquoi l'expliqueraasync
aussi. Contrairement à la plupart des langages qui prennent en charge ce mécanisme, en C #, vous ne pouvez pas direyield value;
à layield return value;
place. Pourquoi? Parce qu'il a été ajouté au langage après que C # existait déjà, et il était tout à fait raisonnable de supposer que quelqu'un, quelque part, aurait pu utiliseryield
le nom d'une variable. Mais parce qu'il n'y avait pas de scénario préexistant dans lequel<variable name> return
était syntaxiquement correct, ayield return
été ajouté au langage pour permettre d'introduire des générateurs tout en maintenant une compatibilité à 100% avec le code existant.Et c'est pourquoi a
async
été ajouté comme modificateur de fonction: pour éviter de casser le code existant utiliséawait
comme nom de variable. Puisqu'aucuneasync
méthode n'existait déjà, aucun ancien code n'est invalidé et dans le nouveau code, le compilateur peut utiliser la présence de laasync
balise pour savoir quiawait
doit être traité comme un mot-clé et non comme un identifiant.la source
async
mot - clé peut être supprimée? De toute évidence, il s'agirait d'une interruption de la Colombie-Britannique, mais on pourrait penser qu'elle affecte très peu de projets et qu'il s'agit d'une simple mise à niveau (c.-à-d. Changer un nom de variable).il change la méthode d'une méthode normale en un objet avec rappel qui nécessite une approche totalement différente pour la génération de code
et quand quelque chose de drastique comme ça arrive, il est habituel de le signifier clairement (nous avons appris cette leçon de C ++)
la source
async
s en même temps afin qu'ils ne s'exécutent pas l'un après l'autre mais simultanément (si les threads sont disponibles au moins)Task<T>
réellement les caractéristiques d'uneasync
méthode - par exemple, vous pouvez simplement exécuter une logique métier / usine, puis déléguer à une autre méthode renvoyantTask<T>
.async
Les méthodes ont un type de retourTask<T>
dans la signature mais ne retournent pas réellement aTask<T>
, elles renvoient juste aT
. Afin de comprendre tout cela sans leasync
mot clé, le compilateur C # devrait effectuer toutes sortes d'inspections approfondies de la méthode, ce qui la ralentirait probablement beaucoup et conduirait à toutes sortes d'ambiguïtés.L'idée avec des mots clés comme "async" ou "unsafe" est de lever toute ambiguïté quant à la façon dont le code qu'ils modifient doit être traité. Dans le cas du mot-clé async, il indique au compilateur de traiter la méthode modifiée comme quelque chose qui n'a pas besoin d'être renvoyé immédiatement. Cela permet au thread où cette méthode est utilisée de continuer sans avoir à attendre les résultats de cette méthode. C'est effectivement une optimisation de code.
la source
OK, voici mon point de vue à ce sujet.
Il y a quelque chose appelé coroutines qui est connu depuis des décennies. ("Knuth and Hopper" -class "pendant des décennies") Ce sont des généralisations de sous - programmes , dans la mesure où non seulement ils obtiennent et relâchent le contrôle au début de la fonction et la déclaration de retour, mais ils le font également à des points spécifiques ( points de suspension ). Un sous-programme est une coroutine sans point de suspension.
Ils sont simples à mettre en œuvre avec des macros C, comme le montre le document suivant sur les "protothreads". ( http://dunkels.com/adam/dunkels06protothreads.pdf ) Lisez-le. J'attendrai...
L'essentiel, c'est que les macros créent un gros
switch
et unecase
étiquette à chaque point de suspension. À chaque point de suspension, la fonction stocke la valeur de l'case
étiquette immédiatement suivante , afin qu'elle sache où reprendre l'exécution la prochaine fois qu'elle sera appelée. Et il rend le contrôle à l'appelant.Cela se fait sans modifier le flux apparent de contrôle du code décrit dans le "protothread".
Imaginez maintenant que vous avez une grande boucle appelant à tour de rôle toutes ces "protothreads" et que vous obtenez simultanément l'exécution de "protothreads" sur un seul thread.
Cette approche présente deux inconvénients:
Il existe des solutions de contournement pour les deux:
Et si vous aviez le support du compilateur pour faire le travail de réécriture que font les macros et la solution de contournement, vous pouvez simplement écrire votre code de prototread comme vous le souhaitez et insérer des points de suspension avec un mot clé.
Et voici ce
async
etawait
sont tous sur: la création (Stackless) coroutines.Les coroutines en C # sont réifiées en tant qu'objets de classe (générique ou non générique)
Task
.Je trouve ces mots clés très trompeurs. Ma lecture mentale est:
async
comme "suspensible"await
comme "suspendre jusqu'à la fin de"Task
comme "futur ..."Maintenant. Avons-nous vraiment besoin de marquer la fonction
async
? En plus de dire qu'il devrait déclencher les mécanismes de réécriture de code pour faire de la fonction une coroutine, il résout certaines ambiguïtés. Considérez ce code.En supposant que ce
async
n'est pas obligatoire, est-ce une coroutine ou une fonction normale? Le compilateur devrait-il le réécrire en coroutine ou non? Les deux pourraient être possibles avec une sémantique éventuelle différente.la source