¿Por qué C # le permite realizar una anulación asincrónica?

16

En C #, cuando anula un método, se permite hacer que la anulación sea asíncrona cuando el método original no lo estaba. Esto parece una forma pobre.

El ejemplo que me llevó a esto fue este: me llevaron para ayudar con un problema de prueba de carga. Con alrededor de 500 usuarios concurrentes, el proceso de inicio de sesión se rompería en un bucle de redireccionamiento. IIS estaba registrando excepciones con el mensaje "Un módulo o controlador asíncrono completado mientras una operación asincrónica aún estaba pendiente". Algunas búsquedas me llevaron a pensar que alguien estaba abusando async void, pero mis búsquedas rápidas a través de la fuente no pudieron encontrar nada.

Lamentablemente, estaba buscando 'async \ svoid' (búsqueda de expresiones regulares) cuando debería haber estado buscando algo más como 'async \ s [^ T]' (suponiendo que la Tarea no estaba completamente calificada ... entiendes el punto).

Lo que más tarde encontré fue async override void onActionExecuting(...en un controlador base. Claramente ese tenía que ser el problema, y ​​lo era. Arreglar eso (haciéndolo sincrónico por el momento) resolvió el problema.

Volver a la pregunta: ¿Por qué, oh, por qué puede marcar una anulación como asíncrona cuando el código de llamada nunca podría esperarla?

Peter T. LaComb Jr.
fuente
3
por favor, no publique mensajes
mosquito
¿Qué inhibe exactamente a la persona que llama para esperar el método anulado? No veo obstáculo.
Martin Maat
@MartinMaat Solo puede esperar los métodos que regresan Task.
Derek Elkins dejó SE
Tal vez ese es un buen punto que no había notado. Tendría que verificar, pero no recuerdo la advertencia de VS sobre la invocación de métodos no asíncronos sin esperar.
Peter T. LaComb Jr.

Respuestas:

16

La palabra clave asincrónica permite que el método use la awaitsintaxis dentro de su definición. Puedo awaiten cualquier método que devuelva un Tasktipo, independientemente de si es un método asíncrono.

voides un tipo de retorno legal (aunque no recomendado ) para un método asíncrono, entonces, ¿por qué no se permitiría? Desde el exterior, asyncno está habilitando nada que no pueda hacer sin él. El método con el que tiene problemas podría haberse escrito para comportarse exactamente igual sin ser asíncrono. Su definición simplemente habría sido más detallada.

Para las personas que llaman, un async Tmétodo es un método normal que los rendimientos T(que se limita a void, Tasko Task<A>). Que es un método asíncrono no es parte de la interfaz. Tenga en cuenta que el siguiente código es ilegal:

interface IFoo {
    async void Bar();
}

(O un código similar en una clase abstracta) produce el siguiente mensaje de error en VS2012:

El modificador 'asíncrono' solo puede usarse en métodos que tienen un cuerpo de declaración

Si yo hice intención de un método en una clase de interfaz o el padre a ser típicamente asíncrona, no puedo utilizar asyncpara comunicar eso. Si quisiera implementarlo con la awaitsintaxis, necesitaría poder tener métodos de anulación asíncrona (en el caso de la clase principal).

Derek Elkins dejó SE
fuente
1
No mencionas overridenada, pero de eso se trata la pregunta.
Nathan Tuggy
44
@NathanTuggy El punto central de la respuesta es que asyncno cambia la interfaz de un método, solo lo que está sintácticamente permitido en su definición, por lo que si es una anulación o no es completamente irrelevante.
Derek Elkins salió del SE
1
Por favor explique eso, en lugar de asumir que todos ya saben todo lo relevante.
Nathan Tuggy
2
@NathanTuggy Siento que lo he explicado. ¿Puedes hacer una pregunta específica acerca de cuál estás confundido o imaginas que otra persona confundida preguntaría? Lo único que se me ocurre agregar es señalar que el asyncmodificador solo se puede aplicar a implementaciones. No puede declarar un método asíncrono en una interfaz, por ejemplo, subrayando que si un método es asíncrono o no, no forma parte de la interfaz.
Derek Elkins dejó SE
55
Pon la explicación en la respuesta , quiero decir. Para eso no están los comentarios a largo plazo.
Nathan Tuggy
10

El único propósito de la palabra clave asíncrona es hacer esperar dentro del cuerpo de esa función una palabra clave. Esto es necesario para que agregar la funcionalidad de espera no rompa el código existente. Microsoft decidió hacer uso de esperar una opción de suscripción. Para una función que no está marcada como asíncrona, puede definir una variable llamada esperar sin problema.

Por lo tanto, async no es parte de la firma de una función y no tiene un significado semántico en el código IL generado. Está estrictamente allí para que el compilador sepa cómo compilar correctamente la función. También le indica al compilador que se asegure de que solo se devuelva Tarea, Tarea <T> o nulo.

Eric Johnson
fuente