programmation - c# task wait



Les opérations asynchrones dans ASP.NET MVC utilisent un thread de ThreadPool sur.NET 4 (4)

Il y a deux concepts en jeu ici. Tout d'abord, nous pouvons faire en sorte que notre code s'exécute en parallèle pour exécuter plus rapidement ou programmer du code sur un autre thread afin d'éviter que l'utilisateur n'attende. L'exemple que vous avez eu

public ViewResult Index() { 

    Task.Factory.StartNew(() => { 
        //Do an advanced looging here which takes a while
    });

    return View();
}

appartient à la deuxième catégorie. L'utilisateur obtiendra une réponse plus rapide mais la charge de travail totale sur le serveur est plus élevée car il doit faire le même travail + gérer le thread.

Un autre exemple de ceci serait:

public ViewResult Index() { 

    Task.Factory.StartNew(() => { 
        //Make async web request to twitter with WebClient.DownloadString()
    });

    Task.Factory.StartNew(() => { 
        //Make async web request to facebook with WebClient.DownloadString()
    });


    //wait for both to be ready and merge the results

    return View();
}

Étant donné que les demandes s'exécutent en parallèle, l'utilisateur n'aura pas à attendre aussi longtemps que si elles ont été effectuées en série. Mais vous devriez vous rendre compte que nous utilisons plus de ressources ici que si nous avons couru en série parce que nous courons le code à de nombreux threads alors que nous avons sur le thread en attente aussi.

C'est parfaitement bien dans un scénario client. Et il est courant d'intégrer du code synchrone à long terme dans une nouvelle tâche (exécutez-le sur un autre thread) et de maintenir l'interface utilisateur sensible ou de la paralléliser pour la rendre plus rapide. Un fil est toujours utilisé pour toute la durée. Sur un serveur avec une charge élevée, cela peut se retourner contre vous parce que vous utilisez réellement plus de ressources. C'est ce que les gens vous ont prévenu

Les contrôleurs asynchrones de MVC ont cependant un autre objectif. Le point ici est d'éviter d'avoir des threads assis autour de ne rien faire (ce qui peut nuire à l'évolutivité). Cela n'a d'importance que si les API que vous appelez ont des méthodes asynchrones. Comme WebClient.DowloadStringAsync ().

Le fait est que vous pouvez laisser votre thread être retourné pour gérer les nouvelles requêtes jusqu'à ce que la requête web soit terminée où elle vous appellera callback qui reçoit le même ou un nouveau thread et termine la requête.

J'espère que vous comprenez la différence entre asynchrone et parallèle. Pensez au code parallèle comme code où votre fil se trouve et attendez le résultat. Alors que le code asynchrone est un code où vous serez averti lorsque le code est terminé et que vous pourrez revenir à travailler dessus, le thread peut alors faire un autre travail.

https://src-bin.com

Après cette question, cela me rend confortable lors de l'utilisation des opérations asynchrones dans ASP.NET MVC. J'ai donc écrit deux articles sur ce blog:

J'ai trop de malentendus dans mon esprit au sujet des opérations asynchrones sur ASP.NET MVC.

J'entends toujours cette phrase: l' application peut mieux évoluer si les opérations s'exécutent de manière asynchrone

Et j'ai souvent entendu ce genre de phrases: si vous avez un très gros volume de trafic, mieux vaut ne pas effectuer vos requêtes de manière asynchrone - en consommant 2 threads supplémentaires pour traiter une requête, les ressources sont retirées des autres requêtes entrantes.

Je pense que ces deux phrases sont incompatibles.

Je n'ai pas beaucoup d'informations sur la façon dont threadpool fonctionne sur ASP.NET, mais je sais que la taille du threadpool est limitée pour les threads. Donc, la deuxième phrase doit être liée à cette question.

Et je voudrais savoir si les opérations asynchrones dans ASP.NET MVC utilise un thread de ThreadPool sur .NET 4?

Par exemple, lorsque nous implémentons un AsyncController, comment l'application se structure-t-elle? Si le trafic est important, est-ce une bonne idée d'implémenter AsyncController?

Y at-il quelqu'un là-bas qui peut prendre ce rideau noir devant mes yeux et m'expliquer l'affaire de l'asynchronie sur ASP.NET MVC 3 (NET 4)?

Modifier:

J'ai lu ce document ci-dessous près de centaines de fois et je comprends l'accord principal, mais j'ai encore de la confusion parce qu'il y a trop de commentaires incohérents.

Utilisation d'un contrôleur asynchrone dans ASP.NET MVC

Modifier:

Supposons que j'ai une action de contrôleur comme ci-dessous (pas une implémentation de AsyncController cependant):

public ViewResult Index() { 

    Task.Factory.StartNew(() => { 
        //Do an advanced looging here which takes a while
    });

    return View();
}

Comme vous le voyez ici, je tire une opération et je l'oublie. Ensuite, je reviens immédiatement sans attendre qu'il soit terminé.

Dans ce cas, faut-il utiliser un thread de threadpool? Si oui, après qu'il se termine, qu'arrive-t-il à ce fil? Est-ce que le GC entre et nettoie juste après l'achèvement?

Modifier:

Pour la réponse de @ Darin, voici un exemple de code asynchrone qui parle à la base de données:

public class FooController : AsyncController {

    //EF 4.2 DbContext instance
    MyContext _context = new MyContext();

    public void IndexAsync() { 

        AsyncManager.OutstandingOperations.Increment(3);

        Task<IEnumerable<Foo>>.Factory.StartNew(() => { 

           return 
                _context.Foos;
        }).ContinueWith(t => {

            AsyncManager.Parameters["foos"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        Task<IEnumerable<Bars>>.Factory.StartNew(() => { 

           return 
                _context.Bars;
        }).ContinueWith(t => {

            AsyncManager.Parameters["bars"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        Task<IEnumerable<FooBar>>.Factory.StartNew(() => { 

           return 
                _context.FooBars;
        }).ContinueWith(t => {

            AsyncManager.Parameters["foobars"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });
    }

    public ViewResult IndexCompleted(
        IEnumerable<Foo> foos, 
        IEnumerable<Bar> bars,
        IEnumerable<FooBar> foobars) {

        //Do the regular stuff and return

    }
}

Answer #1

La première chose n'est pas MVC mais l'IIS qui maintient le pool de threads. Ainsi, toute requête qui vient à l'application MVC ou ASP.NET est servie à partir de threads qui sont maintenus dans le pool de threads. Seulement en faisant l'application Asynch il invoque cette action dans un fil différent et libère le fil immédiatement afin que d'autres demandes puissent être prises.

J'ai expliqué la même chose avec une vidéo de détail ( http://www.youtube.com/watch?v=wvg13n5V0V0/ "Contrôleurs Asynch MVC et thread famine") qui montre comment la famine des fils se produit dans MVC et comment elle est minimisée en utilisant MVC Contrôleurs asynchrones.J'ai également mesuré les files d'attente de requêtes en utilisant perfmon afin que vous puissiez voir comment les files d'attente de demandes sont diminuées pour MVC asynch et comment c'est pire pour les opérations Synch.


Answer #2

Oui - tous les threads proviennent du pool de threads. Votre application MVC est déjà multi-threadée, lorsqu'une requête vient dans un nouveau thread sera pris du pool et utilisé pour traiter la demande. Ce thread sera «verrouillé» (à partir d'autres demandes) jusqu'à ce que la demande soit entièrement traitée et terminée. S'il n'y a pas de thread disponible dans le pool, la requête devra attendre que l'un d'entre eux soit disponible.

Si vous avez des contrôleurs asynchrones, ils reçoivent toujours un thread du pool, mais pendant le traitement de la requête ils peuvent abandonner le thread, en attendant que quelque chose se produise (et ce thread peut être donné à une autre requête) et quand la requête originale a besoin d'un thread encore une fois il en obtient un de la piscine.

La différence est que si vous avez beaucoup de demandes de longue durée (où le thread attend une réponse de quelque chose), vous pouvez manquer de threads à partir du pool pour répondre aux requêtes de base. Si vous avez des contrôleurs asynchrones, vous n'avez plus de threads mais les threads en attente sont renvoyés au pool et peuvent traiter d'autres requêtes.

Un exemple presque réel ... Pensez à monter dans un bus, il y a cinq personnes qui attendent, le premier monte, paie et s'assied (le chauffeur répond à sa demande), vous continuez (le chauffeur entretient votre demande) mais vous ne pouvez pas trouver votre argent; Alors que vous tâtonnez dans vos poches, le chauffeur renonce à vous et obtient les deux personnes suivantes (service de leurs demandes), quand vous trouvez votre argent, le chauffeur commence à traiter avec vous à nouveau (remplir votre demande) - la cinquième personne doit attendre Vous avez terminé, mais les troisième et quatrième personnes ont été servies pendant que vous étiez à mi-chemin pour être servi. Cela signifie que le conducteur est le seul et unique thread de la piscine et que les passagers sont les demandes. C'était trop compliqué d'écrire comment ça marcherait s'il y avait deux pilotes mais vous pouvez imaginer ...

Sans un contrôleur asynchrone, les passagers derrière vous devraient attendre des heures pendant que vous cherchiez votre argent, pendant ce temps le chauffeur de bus ne ferait aucun travail.

Donc la conclusion est, si beaucoup de gens ne savent pas où est leur argent (c.-à-d. Besoin de beaucoup de temps pour répondre à quelque chose que le conducteur a demandé) les contrôleurs asynchrones pourraient bien aider le traitement des demandes. Sans contrôleur Aysnc, tout le monde attend que la personne en face soit complètement traitée. MAIS ne pas oublier que dans MVC vous avez beaucoup de chauffeurs de bus sur un seul bus, async n'est pas un choix automatique.


Answer #3

Oui, ils utilisent un thread du pool de threads. Il existe en fait un excellent guide de MSDN qui répondra à toutes vos questions et plus encore. Je l'ai trouvé très utile par le passé. Vérifiez-le!

http://msdn.microsoft.com/en-us/library/ee728598.aspx

En attendant, les commentaires + suggestions que vous entendez sur le code asynchrone devraient être pris avec un grain de sel. Pour commencer, il suffit de faire quelque chose d'asynchrone pour améliorer l'échelle et, dans certains cas, d'aggraver l'échelle de votre application. L'autre commentaire que vous avez posté sur "un énorme volume de trafic ..." n'est également correct que dans certains contextes. Cela dépend vraiment de ce que font vos opérations et de leur interaction avec d'autres parties du système.

En bref, beaucoup de gens ont beaucoup d'opinions sur l'async, mais ils peuvent ne pas être corrects hors contexte. Je dirais de me concentrer sur vos problèmes exacts, et faire des tests de performance de base pour voir ce que les contrôleurs asynchrones, etc., traitent réellement avec votre application.





asynchronous