Quand dois-je utiliser les contrôleurs asynchrones dans ASP.NET MVC?

J’ai des problèmes avec les actions asynchrones dans ASP.NET MVC. Quand améliore-t-il les performances de mes applications et à quel moment?

  1. Est-il bon d’utiliser une action asynchrone partout dans ASP.NET MVC?
  2. Concernant les méthodes attendues: dois-je utiliser des mots-clés asynchrones / d’attente lorsque je souhaite interroger une firebase database (via EF / NHibernate / other ORM)?
  3. Combien de fois puis-je utiliser des mots-clés en attente pour interroger la firebase database de manière asynchrone en une seule action?

Les méthodes d’ action asynchrones sont utiles lorsqu’une action doit exécuter plusieurs opérations longues et indépendantes.

Les appels de service Web de longue durée constituent une utilisation typique de la classe AsyncController.

Mes appels de firebase database doivent-ils être asynchrones?

Le pool de threads IIS peut souvent gérer beaucoup plus de requêtes de blocage simultanées qu’un serveur de firebase database. Si la firebase database est le goulot d’étranglement, les appels asynchrones n’accélèrent pas la réponse de la firebase database. Sans mécanisme de limitation, l’envoi efficace de plus de travail à un serveur de firebase database surchargé à l’aide d’appels asynchrones ne fait que déplacer davantage la charge vers la firebase database. Si votre firebase database est le goulot d’étranglement, les appels asynchrones ne seront pas la solution miracle.

Vous devriez regarder 1 et 2 références

Dérivé de @PanagiotisKanavos commentaires:

De plus, async ne signifie pas parallèle. L’exécution asynchrone libère un thread threadpool précieux du blocage pour une ressource externe, sans complexité ni coût de performance. Cela signifie que la même machine IIS peut gérer plus de demandes simultanées, et non qu’elle s’exécutera plus rapidement.

Vous devez également considérer que le blocage des appels commence par un spinwait exigeant beaucoup de ressources processeur. Pendant les périodes de stress, le blocage des appels entraînera une augmentation des délais et le recyclage du pool d’applications. Les appels asynchrones évitent simplement cela

Vous pouvez trouver mon article MSDN sur le sujet utile ; J’ai pris beaucoup de place dans cet article pour décrire quand utiliser async sur ASP.NET, et pas seulement comment utiliser async sur ASP.NET.

J’ai des problèmes avec les actions asynchrones dans ASP.NET MVC. Quand il améliore les performances de mes applications et quand – pas.

Tout d’abord, async que l’ async / await est tout à propos de libérer des threads . Sur les applications GUI, il s’agit principalement de libérer le thread d’interface graphique pour que l’expérience utilisateur soit meilleure. Sur les applications de serveur (y compris ASP.NET MVC), il s’agit principalement de libérer le thread de requête afin que le serveur puisse évoluer.

En particulier, ça ne va pas:

  • Rendez vos requêtes individuelles plus rapides. En fait, ils se termineront (juste un petit peu) plus lentement.
  • Revenez à l’appelant / au navigateur lorsque vous rencontrez une await . await que “rendements” pour le pool de threads ASP.NET, pas pour le navigateur.

La première question est la suivante: est-il utile d’utiliser une action asynchrone partout dans ASP.NET MVC?

Je dirais que c’est bon de l’utiliser partout où vous faites des E / S. Cela ne sera pas nécessairement bénéfique (voir ci-dessous).

Cependant, il est mauvais de l’utiliser pour les méthodes liées au processeur. Parfois, les développeurs pensent pouvoir bénéficier des avantages de l’ async en appelant simplement Task.Run dans leurs contrôleurs, et c’est une idée horrible. Parce que ce code finit par libérer le thread de demande en prenant un autre thread, il n’y a donc aucun avantage (et en fait, ils prennent la peine de passer des threads supplémentaires)!

Dois-je utiliser des mots-clés asynchrones / d’attente lorsque je veux interroger une firebase database (via EF / NHibernate / other ORM)?

Vous pouvez utiliser toutes les méthodes attendues disponibles. À l’heure actuelle, la plupart des principaux acteurs supportent l’ async , mais certains ne le font pas. Si votre ORM ne prend pas en charge l’ async , n’essayez pas de l’envelopper dans Task.Run ou quelque chose du genre (voir ci-dessus).

Notez que j’ai dit “vous pourriez utiliser”. Si vous parlez d’ASP.NET MVC avec un backend de firebase database unique, alors vous n’allez (presque certainement) pas bénéficier de l’évolutivité de l’ async . Cela est dû au fait qu’IIS peut gérer beaucoup plus de requêtes simultanées qu’une seule instance de SQL Server (ou un autre SGBDR classique). Cependant, si votre système dorsal est plus moderne – un cluster de serveurs SQL, Azure SQL, NoSQL, etc. – et que votre système dorsal peut évoluer et que votre goulot d’étranglement est IIS, vous pouvez tirer profit de l’ async .

Troisième question – Combien de fois puis-je utiliser des mots-clés en attente pour interroger la firebase database de manière asynchrone en une seule méthode d’action?

Autant que vous le souhaitez. Cependant, notez que de nombreux ORM ont une règle à une opération par connexion. En particulier, EF n’autorise qu’une seule opération par DbContext; Cela est vrai que l’opération soit synchrone ou asynchrone.

Gardez également à l’esprit l’évolutivité de votre backend. Si vous frappez une seule instance de SQL Server et que votre serveur IIS est déjà capable de maintenir SQLServer à pleine capacité, doubler ou sortingpler la pression sur SQLServer ne vous aidera pas du tout.

est-il utile d’utiliser l’action asynchrone partout dans ASP.NET MVC?

Comme d’habitude en programmation, ça dépend . Il y a toujours un compromis quand on descend un certain chemin.

async-await brille dans les endroits où vous savez que vous allez recevoir des demandes simultanées à votre service et que vous voulez être en mesure de bien évoluer. Comment async-await aide-t-il à la montée en charge? Dans le fait que lorsque vous appelez de manière synchrone un appel d’E / S asynchrone, tel qu’un appel réseau ou que vous frappez votre firebase database, le thread en cours qui est responsable de l’exécution est bloqué en attendant que la demande soit terminée. Lorsque vous utilisez async-await , vous activez le framework pour créer pour vous une machine à états qui, une fois l’appel E / S terminé, continue à s’exécuter à partir de là où elle s’est arrêtée.

Une chose à noter est que cette machine à états a une surcharge subtile. Rendre une méthode asynchrone ne l’exécute pas plus rapidement , ce qui est un facteur important à comprendre et une idée fausse que beaucoup de personnes ont.

Une autre chose à prendre en compte lors de l’utilisation de async-await est le fait qu’il est asynchrone tout au long du processus , ce qui signifie que vous allez voir l’async pénétrer toute votre stack d’appels, de haut en bas. Cela signifie que si vous souhaitez exposer des API synchrones, vous vous retrouvez souvent à dupliquer une certaine quantité de code, car les fonctions asynchrone et synchrone ne se mélangent pas très bien.

Dois-je utiliser des mots-clés asynchrones / d’attente lorsque je veux interroger une firebase database (via EF / NHibernate / other ORM)?

Si vous choisissez d’utiliser les appels asynchrones, alors oui, async-await sera un bon choix car de plus en plus de fournisseurs de bases de données exposent des méthodes asynchrones implémentant le TAP (Task Asynchronous Pattern).

Combien de fois puis-je utiliser des mots-clés en attente pour interroger la firebase database de manière asynchrone en une seule méthode d’action?

Autant que vous le souhaitez, tant que vous suivez les règles énoncées par votre fournisseur de firebase database. La quantité d’appels asynchrones que vous pouvez effectuer est illimitée. Si vous avez des requêtes indépendantes les unes des autres et que vous pouvez les faire simultanément, vous pouvez lancer une nouvelle tâche pour chacune d’entre elles et utiliser await Task.WhenAll pour attendre que les deux await Task.WhenAll se terminent.

async actions async sont plus async lorsque les actions effectuent des opérations I / O sur la firebase database ou sur certains appels liés au réseau où le thread qui traite la demande sera bloqué avant de recevoir la réponse de l’appel DB ou réseau que vous venez d’invoquer. Il est préférable que vous utilisiez l’attente avec eux et que cela améliorera vraiment la réactivité de votre application (car moins de threads d’entrée / sortie ASP seront bloqués en attendant la firebase database ou toute autre opération de ce type). Dans toutes mes applications, lorsque de nombreux appels à la firebase database sont nécessaires, je les ai toujours intégrés dans une méthode compréhensible et je les ai appelés avec un mot-clé wait.

Mes 5 cents:

  1. Utilisez async/await si et seulement si vous effectuez une opération IO, comme DB ou un service Web de service externe.
  2. Préférez toujours les appels asynchrones à la firebase database.
  3. Chaque fois que vous interrogez la firebase database.

PS Il existe des cas exceptionnels pour le point 1, mais vous devez bien comprendre les composants internes asynchrones.

Comme avantage supplémentaire, vous pouvez faire peu d’appels IO en parallèle si nécessaire:

 Task task1 = FooAsync(); // launch it, but don't wait for result Task task2 = BarAsync(); // launch bar; now both foo and bar are running await Task.WhenAll(task1, task2); // this is better in regard to exception handling // use task1.Result, task2.Result 

Comme vous le savez, MVC prend en charge les contrôleurs asynchrones et vous devriez en tirer parti. Si votre contrôleur effectue une longue opération (il peut s’agir d’une E / S sur disque ou d’un appel réseau vers un autre service distant), si la requête est gérée de manière synchrone, le thread IIS est occupé tout le temps. Par conséquent, le thread n’attend que la longue opération. Il peut être mieux utilisé en servant d’autres demandes pendant que l’opération demandée en premier est en cours. Cela aidera à servir plus de demandes simultanées. Votre webservice sera hautement évolutif et ne rencontrera pas de problème avec C10k . C’est une bonne idée d’utiliser async / waiting pour les requêtes de firebase database. et oui, vous pouvez les utiliser autant de fois que vous le souhaitez.

Jetez un coup d’oeil ici pour d’excellents conseils.