En C #, lorsque vous remplacez une méthode, il est autorisé de faire la substitution asynchrone alors que la méthode d'origine ne l'était pas. Cela semble être une mauvaise forme.
L'exemple qui m'a amené à ceci est le suivant: j'ai été amené pour aider avec un problème de test de charge. À environ 500 utilisateurs simultanés, le processus de connexion se décomposerait en une boucle de redirection. IIS enregistrait des exceptions avec le message "Un module ou un gestionnaire asynchrone s'est terminé alors qu'une opération asynchrone était toujours en attente". Certaines recherches m'ont amené à penser que quelqu'un abusait async void
, mais mes recherches rapides dans la source n'ont rien trouvé.
Malheureusement, je cherchais «async \ svoid» (recherche d'expression régulière) alors que j'aurais dû chercher quelque chose de plus comme «async \ s [^ T]» (en supposant que la tâche n'était pas pleinement qualifiée… vous obtenez le point).
Ce que j'ai trouvé plus tard était async override void onActionExecuting(...
dans un contrôleur de base. De toute évidence, cela devait être le problème, et c'était le cas. Le corriger (le rendre synchrone pour le moment) a résolu le problème.
Retour à la question: pourquoi oh pourquoi pouvez-vous marquer un remplacement comme asynchrone alors que le code appelant ne pourrait jamais l'attendre?
Task
.Réponses:
Le mot clé async permet à la méthode d'utiliser la
await
syntaxe dans sa définition. Je peuxawait
sur n'importe quelle méthode qui renvoie unTask
type, qu'il s'agisse d'une méthode asynchrone.void
est un type de retour légal (quoique déconseillé ) pour une méthode asynchrone, alors pourquoi ne serait-il pas autorisé? De l'extérieur,async
ne permet rien de ce que vous ne pourriez pas faire sans. La méthode avec laquelle vous rencontrez des problèmes aurait pu être écrite pour se comporter exactement de la même manière sans être asynchrone. Sa définition aurait simplement été plus détaillée.Pour les appelants, une
async T
méthode est une méthode normale que les rendementsT
(qui est limitée àvoid
,Task
ouTask<A>
). Le fait qu'il s'agisse d'une méthode asynchrone ne fait pas partie de l'interface. Notez que le code suivant est illégal:Il (ou un code similaire dans une classe abstraite) génère le message d'erreur suivant dans VS2012:
Si je l'ai fait l' intention d' une méthode dans une interface ou une classe parent à être généralement asynchrones, je ne peux pas utiliser
async
pour communiquer cela. Si je voulais l'implémenter avec laawait
syntaxe, j'aurais besoin d'avoir des méthodes de substitution asynchrone (dans le cas de la classe parent).la source
override
du tout, mais c'est de cela qu'il s'agit.async
cela ne change pas l'interface d'une méthode, seulement ce qui est autorisé syntaxiquement dans sa définition, donc que ce soit un remplacement ou non est complètement hors de propos.async
modificateur ne peut être appliqué qu'aux implémentations. Vous ne pouvez pas déclarer une méthode asynchrone dans une interface, par exemple, en soulignant que si une méthode est asynchrone ou non ne fait pas partie de l'interface.Le seul but du mot-clé async est de faire attendre dans le corps de cette fonction un mot-clé. Cela est nécessaire pour que l'ajout de la fonctionnalité d'attente n'ait pas cassé le code existant. Microsoft a décidé d'utiliser l'attente d'une option d'opt-in. Pour une fonction qui n'est pas marquée async, vous pouvez définir une variable nommée wait sans problème.
Par conséquent, async ne fait pas partie de la signature d'une fonction et n'a aucune signification sémantique dans le code IL généré. Il est strictement là pour que le compilateur sache comment compiler correctement la fonction. Il demande également au compilateur de s'assurer que seuls Task, Task <T> ou void sont retournés.
la source