Asynchronous Controller bloque les requêtes dans ASP.NET MVC via jQuery

Je viens de commencer à utiliser AsyncController dans mon projet pour m'occuper de rapports longs. Il semblait idéal à l'époque, car je pouvais lancer le rapport, puis effectuer quelques autres actions en attendant qu'il revienne et remplisse des éléments sur l'écran.

Mon contrôleur ressemble un peu à cela. J'ai essayé d'utiliser un thread pour effectuer la longue tâche que j'avais espéré libérer le contrôleur pour prendre plus de demandes:

public class ReportsController : AsyncController { public void LongRunningActionAsync() { AsyncManager.OutstandingOperations.Increment(); var newThread = new Thread(LongTask); newThread.Start(); } private void LongTask() { // Do something that takes a really long time //....... AsyncManager.OutstandingOperations.Decrement(); } public ActionResult LongRunningActionCompleted(string message) { // Set some data up on the view or something... return View(); } public JsonResult AnotherControllerAction() { // Do a quick task... return Json("..."); } } 

Mais ce que je trouve, c'est que lorsque j'appelle LongRunningAction à l'aide de la requête jquery ajax, toutes les autres demandes que je fais après la sauvegarde et ne sont pas traitées jusqu'à ce que LongRunningAction soit terminé. Par exemple, appelez LongRunningAction qui prend 10 secondes, puis appelez AnotherControllerAction qui est moins d'une seconde. AnotherControllerAction attend simplement que LongRunningAction soit terminé avant de renvoyer un résultat.

J'ai également vérifié le code jQuery, mais cela se produit toujours si j'ai défini spécifiquement "async: true":

 $.ajax({ async: true, type: "POST", url: "/Reports.aspx/LongRunningAction", dataType: "html", success: function(data, textStatus, XMLHttpRequest) { // ... }, error: function(XMLHttpRequest, textStatus, errorThrown) { // ... } }); 

Pour le moment, je dois supposer que je l'utilise de manière incorrecte, mais j'espère que l'un d'entre vous peut effacer mon bloc mental!

    Il y a deux problèmes en jeu ici. Le premier est que votre contrôleur n'est pas vraiment asynchrone. Le filage d'un thread ThreadPool pour effectuer un travail a généralement des caractéristiques de performances pires que de simplement tout faire à partir de la méthode d'action elle-même, car vous supprimez encore les ressources ThreadPool d'ASP.NET (qui partage simplement le CLR ThreadPool) et vous êtes maintenant Forçant le CLR et le système d'exploitation à faire du jongler avec les threads. Voir http://msdn.microsoft.com/en-us/library/ee728598.aspx#choosing_synchronous_or_asynchronous_action_methods pour plus d'informations. Fondamentalement, ce que ce lien résume est que si vous ne pouvez pas utiliser les ports d'achalandage d'E / S pour vos opérations asynchrones, il est très peu probable que vous voyez des performances améliorées.

    Le deuxième problème est que ASP.NET MVC prend un verrou de session sur toutes les demandes. Les requêtes multiples au sein d'une session unique seront toujours sérialisées, sinon la Session de l'utilisateur pourrait être corrompue si un contrôleur écrit à Session comme un autre contrôleur essaie de le lire. Voir http://forums.asp.net/t/1501623.aspx pour le contexte et une solution de contournement. MVC 2 Futures a un moyen de désactiver ce verrouillage; Il peut également être inclus dans MVC 3 proprement dit. Voir https://blogs.msdn.com/b/rickandy/archive/2009/12/17/session-less-mvc-controller.aspx pour plus d'informations à ce sujet.

    Acutally le problème se trouve dans ce.HttpContext.Session, parce qu'il est verrouillé, si vous écrivez quelque chose à une session dans votre AsyncController, vous devriez l'éviter et l'utiliser.HttpContext.Application – cela résoudra le problème, j'ai eu le Même problème, et essayez-nous