Quel est l'avantage d'utiliser async avec MVC5?

120

Quelle est la différence 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);
}

et:

[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);
}

Je vois que le code MVC a maintenant async mais quelle est la différence. Est-ce que l'un donne de bien meilleures performances que l'autre? Est-il plus facile de déboguer les problèmes avec l'un que l'autre? Dois-je apporter des modifications à d'autres contrôleurs pour que mon application ajoute Async?

annemartijn
la source
Dans la grande majorité des situations, il n'y a aucun avantage sérieux à utiliser async dans MVC, mais il y a de nombreux inconvénients
Chris Marisic
1
@ChrisMarisic - L'une des plus sérieuses: vous ne pouvez pas utiliser ReaderWriterLock ou l'une des autres primitives de synchronisation (à l'exception de Semaphore).
Quarkly

Réponses:

170

Les actions asynchrones ne sont utiles que lorsque vous effectuez des opérations liées aux E / S telles que les appels de serveur distant. L'avantage de l'appel asynchrone est qu'au cours de l'opération d'E / S, aucun thread de travail ASP.NET n'est utilisé. Alors, voici comment fonctionne le premier exemple:

  1. Lorsqu'une demande atteint l'action, ASP.NET prend un thread du pool de threads et commence à l'exécuter.
  2. La IdentityManager.Authentication.CheckPasswordAndSignInméthode est invoquée. Il s'agit d'un appel bloquant -> pendant tout l'appel, le thread de travail est compromis.

Et voici comment fonctionne le deuxième appel:

  1. Lorsqu'une demande atteint l'action, ASP.NET prend un thread du pool de threads et commence à l'exécuter.
  2. Le IdentityManager.Authentication.CheckPasswordAndSignInAsyncest appelé qui revient immédiatement. Un port d'achèvement d'E / S est inscrit et le thread de travail ASP.NET est libéré dans le pool de threads.
  3. Plus tard, lorsque l'opération se termine, le port d'achèvement d'E / S est signalé, un autre thread est tiré du pool de threads pour terminer le renvoi de la vue.

Comme vous pouvez le voir dans le second cas, les threads de travail ASP.NET ne sont utilisés que pendant une courte période. Cela signifie qu'il y a plus de threads disponibles dans le pool pour traiter d'autres demandes.

Donc, pour conclure, n'utilisez les actions asynchrones que lorsque vous avez une véritable API asynchrone à l'intérieur. Si vous effectuez un appel de blocage dans une action asynchrone, vous en tuez tout le bénéfice.

Darin Dimitrov
la source
Que diriez-vous de la synchronisation de contexte. Cela ne sera-t-il pas tel que vous ne souhaitiez pas du tout utiliser d'actions asynchrones? "La surcharge d'une méthode asynchrone qui s'exécute réellement de manière asynchrone dépend entièrement de la nécessité ou non de changer de thread à l'aide de SynchronizationContext.Post. Si c'est le cas, la surcharge est dominée par le commutateur de thread qu'elle effectue lors de sa reprise. Cela signifie que le SynchronizationContext actuel fait une grosse différence." (Async en C # 5.0, 2012, Alex Davies)
annemartijn
1
@Darin Pourquoi est-il si important de publier le fil de discussion principal? Les threads sont-ils limités?
Omtechguy
1
@Omtechguy une meilleure solution consiste à déplacer les requêtes non ASP.NET vers un CDN. Un CDN simple utilise simplement un sous-domaine et un pool d'applications séparé pour les fichiers physiques tels que votre javascript et vos images. Vous pouvez également utiliser NgineX / Lighttpd / Apache pour les fichiers, ou vous pouvez utiliser un service tiers tel qu'Akamai (roi pour CDN mais le plus cher)
Chris Marisic
Je suis encore confus. Lorsque le CheckPasswordAndSignInAsyncest appelé, ASP.NET prend un autre thread du pool de threads et commence à l'exécuter, n'est-ce pas? Si ce n'est pas le cas, où est-il checking password procedureexécuté?
KevinBui
2

Normalement, une seule requête HTTP serait gérée par un seul thread, supprimant complètement ce thread du pool jusqu'à ce qu'une réponse soit renvoyée. Avec le TPL, vous n'êtes pas lié par cette contrainte. Toute demande qui arrive commence une continuation avec chaque unité de calcul requise pour calculer une réponse capable de s'exécuter sur n'importe quel thread du pool. Avec ce modèle, vous pouvez gérer beaucoup plus de demandes simultanées qu'avec ASP.Net standard.

Si c'est une nouvelle tâche qui sera engendrée, ou non, et si elle doit être attendue ou non. Pensez toujours à ces 70 ms, soit environ. le max. temps que tout appel de méthode devrait prendre. Si c'est plus long, votre interface utilisateur ne ressentira probablement pas une très grande réactivité.

Gaurang Dhandhukiya
la source
0

Dans les applications Web qui voient un grand nombre de requêtes simultanées au démarrage ou qui ont une charge en rafale (où la concurrence augmente soudainement), rendre ces appels de service Web asynchrones augmentera la réactivité de votre application. Une demande asynchrone prend le même temps à traiter qu'une demande synchrone. Par exemple, si une demande effectue un appel de service Web qui nécessite deux secondes pour se terminer, la demande prend deux secondes, qu'elle soit exécutée de manière synchrone ou asynchrone. Toutefois, lors d'un appel asynchrone, un thread n'est pas bloqué de répondre à d'autres demandes pendant qu'il attend la fin de la première demande. Par conséquent, les demandes asynchrones empêchent la mise en file d'attente des demandes et la croissance du pool de threads lorsqu'il existe de nombreuses demandes simultanées qui appellent des opérations de longue durée.

Muhammad Essa
la source
Si votre application aspnet se compose en grande partie d'appels vers d'autres serveurs Web, vous vous comportez en grande partie comme une «passerelle» / «proxy» et async est utile à cette fin.
Chris Marisic