programacion ejemplos await async asincrona c# async-await

asincrona - async await c# ejemplos



¿Por qué C#permite realizar una anulación asincrónica? (3)

Cuando la clase base (o interfaz) declara un método virtual que devuelve una tarea, puede anularlo siempre que devuelva la tarea. La palabra clave async es solo una sugerencia para que el compilador transforme su método en una máquina de estado. Aunque el compilador hace magia negra en su método, el método compilado todavía devuelve una Tarea .

En cuanto a los métodos virtuales void , puede anular uno sin la palabra clave async (obviamente) e iniciar una tarea no esperada dentro de ella. Eso es algo de lo que sucede cuando se anula con la palabra clave async y se usa await en el cuerpo. La persona que llama no esperaría la Tarea creada (ya que la firma "original" es void ). Ambos casos son similares *:

public override void MyVirtualMethod() { // Will create a non awaited Task (explicitly) Task.Factory.StartNew(()=> SomeTaskMethod()); } public override async void MyVirtualMethod() { // Will create a non awaited Task (the caller cannot await void) await SomeTaskMethod(); }

El artículo de Stephen Cleary tiene algunas notas al respecto:

  • Los métodos asíncronos que devuelven el vacío tienen un propósito específico: hacer posibles los controladores asíncronos de eventos.
  • Debe preferir la tarea asíncrona a la anulación asíncrona.

* La implementación de SomeTaskMethod , el marco subyacente, SynchronizationContext y otros factores puede y causará resultados diferentes para cada uno de los métodos anteriores.

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 problema que me hace preguntarme es 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 dividiría en un bucle de redirección. IIS estaba registrando excepciones con el mensaje "Se completó un módulo o controlador asíncrono mientras aún estaba pendiente una operación asíncrona". Algunas búsquedas me llevaron a pensar que alguien estaba abusando de async void , pero mis búsquedas rápidas a través de la fuente no encontraron nada.

Lamentablemente, estaba buscando async/s*void (búsqueda de expresiones regulares) cuando debería haber estado buscando algo más parecido a async/s*[^T] (suponiendo que la tarea no estaba completamente calificada ... entiendes el punto).

Lo que más tarde encontré fue una async override void onActionExecuting en async override void onActionExecuting de 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.

Pero me dejó con una pregunta: ¿Por qué puede marcar una anulación como asincrónica cuando el código de llamada nunca podría esperarla?



async no es parte del "contrato". Es un detalle de implementación que, en mi opinión, desafortunadamente, aparece en el lugar equivocado.

Es perfectamente legal cambiar un método (no async ) convirtiendo una Task en una async (o viceversa) sin que sea un cambio importante, y sin requerir que los llamadores compilen.

Otra indicación de que no forma parte del contrato es que no se le permite marcar funciones como async dentro de las interfaces y, como aquí, es perfectamente posible anular async con no async o viceversa.