Contrôleurs asynchrones dans ASP.NET MVC: avantages réels / comment obtenus?


12

J'ai travaillé sur un article sur les méthodes de contrôleur asynchrone dans ASP.NET MVC ( http://visualstudiomagazine.com/articles/2013/07/23/async-actions-in-aspnet-mvc-4.aspx ) et je pense Je manque peut-être le point.

Considérez cette méthode que j'ai écrite, qui est très similaire à un exemple de l'article:

[HttpGet]
[AsyncTimeout(8000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimedOut")]
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
    WidgetPageViewModel model = new WidgetPageViewModel()
    {
        toAdd = new Widget()
    };
    model.all = await _repo.GetAllAsync(cancellationToken);
    return View(model);
}

Si je comprends bien les choses, voici comment les choses se dérouleront au moment de l'exécution:

  1. Un thread ASP.NET sera créé pour une demande HTTP entrante.

  2. Ce fil entrera (après avoir probablement effectué certains travaux préliminaires nécessaires) dans ma méthode Index () ci-dessus.

  3. L'exécution atteindra le mot clé "wait" et lancera un processus d'acquisition de données sur un autre thread.

  4. Le thread "ASP.NET" d'origine reviendra au code qui a appelé ma méthode de gestionnaire, avec une instance de classe Task comme valeur de retour.

  5. Le code d'infrastructure qui a appelé ma méthode de gestionnaire continuera de fonctionner sur le thread "ASP.NET" d'origine, jusqu'à ce qu'il atteigne un point où il doit utiliser l'objet ActionResult réel (par exemple pour rendre la page).

  6. L'appelant accédera ensuite à cet objet à l'aide du membre Task.Result, ce qui le fera (c'est-à-dire le thread "ASP.NET") attendre le thread créé implicitement à l'étape 3 ci-dessus.

Je ne vois pas ce que cela accomplit par rapport à la même chose sans attendre / async, sauf pour deux choses que je perçois comme insignifiantes:

  • Le thread d'appelant et le thread de travail créé par attendent peuvent fonctionner en parallèle pendant un certain temps (la partie "jusqu'à" de # 5 ci-dessus). Mon intuition est que la période de temps est assez courte. Lorsque l'infrastructure fait appel à une méthode de contrôleur, je pense qu'elle a généralement besoin du résultat ActionResult réel de l'appel de contrôleur avant de pouvoir faire beaucoup (le cas échéant) de plus.

  • Il existe une nouvelle infrastructure utile liée au délai d'expiration et à l'annulation des opérations de contrôleur asynchrone de longue durée.

Le but de l'ajout de méthodes de contrôleur asynchrone est censé libérer ces threads de travail ASP.NET pour réellement répondre aux requêtes HTTP. Ces threads sont une ressource finie. Malheureusement, je ne vois pas comment le modèle suggéré dans l'article sert réellement à conserver ces fils. Et même si c'est le cas, et décharge d'une manière ou d'une autre le fardeau de la gestion de la demande vers un thread nonASP.NET, qu'est-ce que cela accomplit? Les threads capables de gérer une requête HTTP sont-ils si différents des threads en général?


Execution will reach the "await" keyword and kick off a data acquisition process on another thread-- Pas nécessairement. asyncne nécessite pas un autre thread ... C'est une continuation. Cela peut être accompli en réorganisant les instructions sur le même fil.
Robert Harvey


"L'exécution atteindra le mot-clé wait et lancera un processus d'acquisition de données sur un autre thread." vous avez obtenu cela à l'envers: l'attente est quand il revient. Essayez de le diviser pour enregistrer le résultat de GetAllAsync () dans une variable et attendez cela à la place et voyez si cela devient plus clair.
Esben Skov Pedersen

Réponses:


9

ASP.Net qui n'utilise pas la bibliothèque parallèle de tâches (TPL) est limité dans le nombre de demandes qu'il peut gérer simultanément par le nombre de threads dans un pool de threads. ASP.Net qui utilise le TPL est limité par le CPU / mémoire / IO des demandes de traitement de la machine.

La bibliothèque parallèle de tâches (TPL) ne consomme pas de threads comme vous semblez le penser. Les tâches ne sont pas des threads, elles sont un wrapper autour d'une unité de calcul. Le planificateur de tâches est responsable de l'exécution de chaque tâche sur n'importe quel thread qui n'est pas occupé. Au moment de l'exécution, l'attente d'une tâche ne bloque pas le thread, elle ne fait que garer l'état d'exécution pour qu'elle puisse continuer ultérieurement.

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 démarre une suite 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.


Alors, quand le thread ASP.NET est-il renvoyé au pool? Lorsque le mot clé "wait" est frappé?
user1172763

async / attendent + TPL permettent au compilateur de diviser votre code en unités de calcul indépendantes qui sont exécutées par le planificateur de tâches. Un thread est conceptuellement renvoyé au pool lorsque le planificateur de tâches n'a plus de tâches pouvant être exécutées et que le thread termine le travail qui lui est confié.
mortalapeman

C'est conceptuellement correct et probablement une réponse utile ... mais la réalité est juste un peu plus compliquée en raison de l' agilité des threads .
John Wu
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.