Solución:
Puede encontrar útil mi artículo de MSDN sobre el tema; Tomé mucho espacio en ese artículo que describe cuando deberías usar async
en ASP.NET, no solo cómo usar async
en ASP.NET.
Tengo algunas preocupaciones sobre el uso de acciones asíncronas en ASP.NET MVC. Cuándo mejora el rendimiento de mis aplicaciones y cuándo no.
Primero, entiende que async
/await
se trata de liberando hilos. En las aplicaciones GUI, se trata principalmente de liberando el hilo de la GUI para que la experiencia del usuario sea mejor. En las aplicaciones de servidor (incluido ASP.NET MVC), se trata principalmente de liberando el hilo de solicitud para que el servidor pueda escalar.
En particular, no:
- Haga que sus solicitudes individuales se completen más rápido. De hecho, se completarán (solo un poquito) más lento.
- Regrese a la persona que llama / navegador cuando presione un
await
.await
sólo “cede” al grupo de subprocesos ASP.NET, no al navegador.
La primera pregunta es: ¿es bueno usar la acción asíncrona en todas partes en ASP.NET MVC?
Yo diría que es bueno usarlo en cualquier lugar donde esté haciendo E / S. Puede que no sea necesariamente beneficioso, aunque (ver más abajo).
Sin embargo, es malo para usarlo para métodos vinculados a la CPU. A veces, los desarrolladores piensan que pueden obtener los beneficios de async
con solo llamar Task.Run
en sus controladores, y esta es una idea horrible. Debido a que ese código termina liberando el subproceso de solicitud al tomar otro subproceso, por lo que no hay ningún beneficio en absoluto (y, de hecho, ¡están tomando la penalización de los cambios de subproceso adicionales)!
¿Debo usar palabras clave asíncronas / en espera cuando quiero consultar la base de datos (a través de EF / NHibernate / otro ORM)?
Podrías usar cualquier método que tengas disponible. En este momento, la mayoría de los principales jugadores apoyan async
, pero hay algunos que no lo hacen. Si su ORM no es compatible async
, entonces no intentes envolverlo Task.Run
o algo por el estilo (ver arriba).
Tenga en cuenta que dije “usted podría use “. Si está hablando de ASP.NET MVC con un solo backend de base de datos, entonces (casi con certeza) no obtendrá ningún beneficio de escalabilidad de async
. Esto se debe a que IIS puede manejar muchas más solicitudes simultáneas que una sola instancia de SQL Server (u otro RDBMS clásico). Sin embargo, si su backend es más moderno (un clúster de servidor SQL, Azure SQL, NoSQL, etc.) y su backend puede escalar, y su cuello de botella de escalabilidad es IIS, luego puede obtener un beneficio de escalabilidad async
.
Tercera pregunta: ¿cuántas veces puedo usar las palabras clave de espera para consultar la base de datos de forma asíncrona en UN método de acción única?
Tantos como quieras. Sin embargo, tenga en cuenta que muchos ORM tienen una regla de una operación por conexión. En particular, EF solo permite una única operación por DbContext; esto es cierto tanto si la operación es síncrona como asincrónica.
Además, tenga en cuenta la escalabilidad de su backend nuevamente. Si está utilizando una sola instancia de SQL Server y su IIS ya es capaz de mantener SQLServer a plena capacidad, duplicar o triplicar la presión sobre SQLServer no lo ayudará en absoluto.
Acción asincrónica Los métodos son útiles cuando una acción debe realizar varias operaciones independientes de larga ejecución.
Un uso típico de la clase AsyncController son las llamadas de servicio web de larga duración.
¿Deben ser asincrónicas mis llamadas a la base de datos?
El grupo de subprocesos de IIS a menudo puede manejar muchas más solicitudes de bloqueo simultáneas que un servidor de base de datos. Si la base de datos es el cuello de botella, las llamadas asincrónicas no acelerarán la respuesta de la base de datos. Sin un mecanismo de limitación, el envío eficiente de más trabajo a un servidor de base de datos abrumado mediante el uso de llamadas asincrónicas simplemente transfiere más carga a la base de datos. Si su base de datos es el cuello de botella, las llamadas asincrónicas no serán la solución mágica.
usted deberían echa un vistazo a las referencias 1 y 2
Derivado de los comentarios de @PanagiotisKanavos:
Además, async no significa paralelo. La ejecución asincrónica libera un subproceso valioso de la agrupación de subprocesos del bloqueo de un recurso externo, sin costo de complejidad o rendimiento. Esto significa que la misma máquina IIS puede manejar más solicitudes simultáneas, no que se ejecutará más rápido.
También debe considerar que las llamadas de bloqueo comienzan con un spinwait con uso intensivo de la CPU. Durante tiempos de estrés, el bloqueo de llamadas dará como resultado retrasos cada vez mayores y el reciclaje del grupo de aplicaciones. Las llamadas asincrónicas simplemente evitan esto
¿Es bueno usar la acción asíncrona en todas partes en ASP.NET MVC?
Como es habitual en la programación, depende. Siempre hay una compensación cuando se recorre un camino determinado.
async-await
brilla en lugares donde sabe que recibirá solicitudes simultáneas a su servicio y desea poder poner a escala bien. Cómo async-await
ayuda con el escalado horizontal? En el hecho de que cuando invoca una llamada IO asincrónica sincrónicamente, como una llamada de red o acceder a su base de datos, el hilo actual que es responsable de la ejecución se bloquea a la espera de que finalice la solicitud. Cuando usas async-await
, habilita el marco para crear una máquina de estado para usted, lo que se asegura de que después de que se complete la llamada IO, su método continúe ejecutándose desde donde lo dejó.
Una cosa a tener en cuenta es que esta máquina de estado tiene una sobrecarga sutil. Hacer un método asincrónico no hace que se ejecute más rápido, y ese es un factor importante de entender y un concepto erróneo que muchas personas tienen.
Otra cosa a tener en cuenta al usar async-await
es el hecho de que es asincrónico todo el camino, lo que significa que verá que async penetra en toda su pila de llamadas, de arriba a abajo. Esto significa que si desea exponer API síncronas, a menudo se encontrará duplicando una cierta cantidad de código, ya que la sincronización y la sincronización no se mezclan muy bien.
¿Debo usar palabras clave asíncronas / en espera cuando quiero consultar la base de datos (a través de EF / NHibernate / otro ORM)?
Si elige seguir el camino del uso de llamadas IO asíncronas, entonces sí, async-await
será una buena opción, ya que los proveedores de bases de datos cada vez más modernos exponen el método asíncrono que implementa el TAP (patrón asíncrono de tareas).
¿Cuántas veces puedo usar palabras clave de espera para consultar la base de datos de forma asincrónica en UN método de acción única?
Tantas como desee, siempre que siga las reglas establecidas por su proveedor de base de datos. No hay límite para la cantidad de llamadas asíncronas que puede realizar. Si tiene consultas que son independientes entre sí y se pueden realizar al mismo tiempo, puede girar una nueva tarea para cada una y usar await Task.WhenAll
esperar a que se completen ambos.