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

14

En C #, cuando reemplaza un método, está permitido hacer que el reemplazo sea asíncrono cuando el método original no lo era. Esto parece ser una mala forma.

El ejemplo que me llevó a esto fue el siguiente: me trajeron para ayudar con un problema de prueba de carga. En alrededor de 500 usuarios simultáneos, el proceso de inicio de sesión se rompería en un bucle de redirección. IIS estaba registrando excepciones con el mensaje "Un módulo o controlador asíncrono se completó mientras una operación asincrónica aún estaba pendiente". Algunas búsquedas me llevaron a pensar que alguien estaba abusando de async void , pero mis búsquedas rápidas en 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]' (asumiendo que Task no estaba completamente calificado ... entiendes el punto ).

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

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

    
pregunta Peter T. LaComb Jr. 05.03.2016 - 19:00

2 respuestas

15

La palabra clave async permite que el método use el await sintaxis dentro de su definición. Puedo await en cualquier método que devuelva un tipo Task sin importar si es un método asíncrono.

void es un tipo de devolución legal (aunque desaconsejado ) para un método asíncrono, Entonces, ¿por qué no sería permitido? Desde el exterior, async no habilita nada que no puedas hacer sin él. El método con el que tiene problemas podría haberse escrito para que se comporte exactamente igual sin ser asíncrono. Su definición simplemente habría sido más detallada.

Para las personas que llaman, un método async T es un método normal que devuelve T (que está limitado a void , Task o Task<A> ). Que sea un método asíncrono no forma 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 se puede usar en métodos que tienen una declaración   cuerpo

Si hice pretendía que un método en una interfaz o clase principal fuera normalmente asíncrono, no puedo usar async para comunicarlo. Si quisiera implementarlo con la sintaxis await , necesitaría poder tener métodos de anulación asíncronos (en el caso de la clase principal).

    
respondido por el Derek Elkins 05.03.2016 - 20:41
10

El único propósito de la palabra clave asíncrona es hacer esperar en el cuerpo de esa función una palabra clave. Esto es necesario para que la adición de 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 aguardar 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. Es 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 Tarea, Tarea < T > o se devuelve void.

    
respondido por el Eric Johnson 05.03.2016 - 23:43

Lea otras preguntas en las etiquetas