Pourquoi C # vous permet-il de faire une asynchronisation de remplacement?

16

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?

Peter T. LaComb Jr.
la source
3
s'il vous plaît ne pas cross-post : stackoverflow.com/questions/35817558/…
gnat
Qu'est-ce qui empêche exactement un appelant d'attendre la méthode remplacée? Je ne vois aucun obstacle.
Martin Maat
@MartinMaat Vous ne pouvez attendre que les méthodes qui reviennent Task.
Derek Elkins a quitté le SE
C'est peut-être un bon point que je n'avais pas remarqué. Je devrais vérifier, mais je ne me souviens pas de l'avertissement de VS concernant l'appel de méthodes non asynchrones sans attendre.
Peter T. LaComb Jr.

Réponses:

16

Le mot clé async permet à la méthode d'utiliser la awaitsyntaxe dans sa définition. Je peux awaitsur n'importe quelle méthode qui renvoie un Tasktype, qu'il s'agisse d'une méthode asynchrone.

voidest 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, asyncne 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 Tméthode est une méthode normale que les rendements T(qui est limitée à void, Taskou Task<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:

interface IFoo {
    async void Bar();
}

Il (ou un code similaire dans une classe abstraite) génère le message d'erreur suivant dans VS2012:

Le modificateur 'async' ne peut être utilisé que dans les méthodes qui ont un corps d'instruction

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 asyncpour communiquer cela. Si je voulais l'implémenter avec la awaitsyntaxe, j'aurais besoin d'avoir des méthodes de substitution asynchrone (dans le cas de la classe parent).

Derek Elkins a quitté SE
la source
1
Vous n'en parlez pas overridedu tout, mais c'est de cela qu'il s'agit.
Nathan Tuggy
4
@NathanTuggy Le point essentiel de la réponse est que asynccela 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.
Derek Elkins a quitté le SE
1
Veuillez expliquer cela, plutôt que de supposer que tout le monde connaît déjà tout ce qui est pertinent.
Nathan Tuggy
2
@NathanTuggy J'ai l'impression de l'avoir expliqué. Pouvez-vous poser une question précise à propos de laquelle vous êtes confus ou vous imaginez qu'une autre personne confuse poserait? La seule chose que je peux penser d'ajouter est de souligner que le asyncmodificateur 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.
Derek Elkins a quitté le SE
5
Mettez l'explication dans la réponse , je veux dire. Ce ne sont pas les commentaires à long terme.
Nathan Tuggy
10

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.

Eric Johnson
la source