¿Cuál es la ventaja de usar async con MVC5?

120

Cuál es la diferencia entre:

public ActionResult Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        IdentityResult result = IdentityManager.Authentication.CheckPasswordAndSignIn(AuthenticationManager, model.UserName, model.Password, model.RememberMe);
        if (result.Success)
        {
            return Redirect("~/home");
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(model);
}

y:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        IdentityResult result = await IdentityManager.Authentication.CheckPasswordAndSignInAsync(AuthenticationManager, model.UserName, model.Password, model.RememberMe);
        if (result.Success)
        {
            return Redirect("~/home");
        }
        else
        {
            AddErrors(result);
        }
    }
    return View(model);
}

Veo que el código MVC ahora tiene async pero cuál es la diferencia. ¿Ofrece uno un rendimiento mucho mejor que el otro? ¿Es más fácil depurar problemas con uno que con el otro? ¿Debo realizar cambios en otros controladores para que mi aplicación agregue Async?

Annemartijn
fuente
En la gran mayoría de las situaciones, no existe un beneficio serio por usar async en MVC, sin embargo, hay muchos
aspectos
1
@ChrisMarisic - Uno de los más serios: no puede usar ReaderWriterLock ni ninguna de las otras primitivas de sincronización (excepto Semaphore).
Quarkly

Respuestas:

170

Las acciones asíncronas son útiles solo cuando realiza operaciones vinculadas de E / S, como llamadas a servidores remotos. El beneficio de la llamada asíncrona es que durante la operación de E / S, no se utiliza ningún subproceso de trabajo ASP.NET. Así es como funciona el primer ejemplo:

  1. Cuando una solicitud llega a la acción, ASP.NET toma un subproceso del grupo de subprocesos y comienza a ejecutarlo.
  2. Se IdentityManager.Authentication.CheckPasswordAndSignIninvoca el método. Esta es una llamada de bloqueo -> durante toda la llamada, el hilo de trabajo se pone en peligro.

Y así es como funciona la segunda llamada:

  1. Cuando una solicitud llega a la acción, ASP.NET toma un subproceso del grupo de subprocesos y comienza a ejecutarlo.
  2. Se IdentityManager.Authentication.CheckPasswordAndSignInAsyncllama que regresa inmediatamente. Se registra un puerto de finalización de E / S y el subproceso de trabajo ASP.NET se libera al grupo de subprocesos.
  3. Más tarde, cuando se completa la operación, se señala el puerto de finalización de E / S, se extrae otro subproceso del grupo de subprocesos para terminar de devolver la vista.

Como puede ver en el segundo caso, los subprocesos de trabajo de ASP.NET se utilizan solo durante un corto período de tiempo. Esto significa que hay más subprocesos disponibles en el grupo para atender otras solicitudes.

Entonces, para concluir, use acciones asíncronas solo cuando tenga una verdadera API asíncrona dentro. Si realiza una llamada de bloqueo dentro de una acción asincrónica, está matando todo el beneficio de ella.

Darin Dimitrov
fuente
¿Qué hay de la sincronización de contexto? ¿No será esto una sobrecarga que no desee utilizar acciones asíncronas en absoluto? "La sobrecarga de un método asíncrono que realmente se ejecuta de forma asincrónica depende completamente de si necesita cambiar de hilo usando SynchronizationContext.Post. Si lo hace, la sobrecarga está dominada por el cambio de hilo que realiza cuando se reanuda. Eso significa que el SynchronizationContext actual hace una gran diferencia." (Async en C # 5.0, 2012, Alex Davies)
annemartijn
1
@Darin ¿Por qué es tan importante liberar el hilo principal? ¿Están limitados los hilos?
Omtechguy
1
@Omtechguy una mejor solución es mover solicitudes que no sean ASP.NET a un CDN. Un CDN simple simplemente usa un subdominio y un grupo de aplicaciones separado para archivos físicos como su javascript e imágenes. Alternativamente, puede usar NgineX / Lighttpd / Apache para archivos, o puede usar un servicio de terceros como Akamai (rey para CDN pero más caro)
Chris Marisic
Todavía estoy confundido. Cuando CheckPasswordAndSignInAsyncse llama, ASP.NET toma otro subproceso del grupo de subprocesos y comienza a ejecutarlo, ¿no es así? Si no es así, ¿dónde se checking password procedureejecuta?
KevinBui
2

Normalmente, una sola solicitud HTTP sería manejada por un solo hilo, eliminando por completo ese hilo del grupo hasta que se devuelva una respuesta. Con el TPL, no está sujeto a esta restricción. Cualquier solicitud que ingrese comienza una continuación con cada unidad de cálculo requerida para calcular una respuesta capaz de ejecutarse en cualquier hilo del grupo. Con este modelo, puede manejar muchas más solicitudes simultáneas que con ASP.Net estándar.

Si se trata de alguna tarea nueva que se generará, o no, y si se debe esperar o no. Piensa siempre en esos 70 ms, que son aprox. El máximo. tiempo que debería tomar cualquier llamada a método. Si es más largo, lo más probable es que la interfaz de usuario no se sienta muy receptiva.

Gaurang Dhandhukiya
fuente
0

En aplicaciones web que ven una gran cantidad de solicitudes simultáneas al inicio o tienen una carga a ráfagas (donde la concurrencia aumenta repentinamente), hacer que estas llamadas de servicios web sean asincrónicas aumentará la capacidad de respuesta de su aplicación. Una solicitud asincrónica tarda el mismo tiempo en procesarse que una solicitud síncrona. Por ejemplo, si una solicitud realiza una llamada de servicio web que requiere dos segundos para completarse, la solicitud tarda dos segundos, ya sea que se realice de forma sincrónica o asincrónica. Sin embargo, durante una llamada asincrónica, un hilo no está bloqueado para responder a otras solicitudes mientras espera a que se complete la primera solicitud. Por lo tanto, las solicitudes asincrónicas evitan la puesta en cola de solicitudes y el crecimiento del grupo de subprocesos cuando hay muchas solicitudes simultáneas que invocan operaciones de larga duración.

Muhammad Essa
fuente
Si su aplicación aspnet consiste principalmente en llamadas a otros servidores web, se está comportando en gran medida como una 'puerta de enlace' / 'proxy' y async es útil para ese propósito.
Chris Marisic