2010-05-28 11 views
23

Acabo de empezar a usar AsyncController en mi proyecto para encargarme de algunos informes de larga ejecución. Parecía ideal en ese momento, ya que podía iniciar el informe y luego realizar algunas otras acciones mientras esperaba que volviera y llenara elementos en la pantalla.El controlador asíncrono está bloqueando las solicitudes en ASP.NET MVC a través de jQuery

Mi controlador se parece un poco a esto. He intentado utilizar un hilo para realizar la larga tarea que yo esperaba que liberaría el controlador para tener más solicitudes:

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("..."); 
    } 
} 

Pero lo que estoy encontrando es que cuando llamo LongRunningAction usando la solicitud Ajax jQuery, cualquier otra solicitud que realice después de esa copia de seguridad y no se procesa hasta que se complete LongRunningAction. Por ejemplo, llame a LongRunningAction, que demora 10 segundos y luego llama a AnotherControllerAction, que es menos de un segundo. AnotherControllerAction simplemente espera hasta que LongRunningAction finalice antes de devolver un resultado.

también he comprobado el código de jQuery, pero esto todavía sucede si fijo específicamente "asíncrono: true":

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

Por el momento sólo tengo que asumir que estoy usando de manera incorrecta, ¡Pero espero que uno de ustedes pueda despejar mi bloqueo mental!

+0

¿Está haciendo esto en IIS o WebDev? WebDev es, um, "menos agresivamente multiproceso" que IIS. –

+0

Tengo el mismo problema, ¿cómo resolvió el problema? – Tomas

Respuesta

31

Hay dos problemas en juego aquí. El primero es que su controlador no es verdaderamente asincrónico. Alternar un subproceso de ThreadPool para realizar un trabajo generalmente tiene peores características de rendimiento que solo hacer todo desde el propio método de acción, ya que todavía está tomando recursos de ThreadPool desde ASP.NET (que solo comparte el CLR ThreadPool), y ahora está forzando al CLR y al sistema operativo a hacer malabares con los hilos. Ver http://msdn.microsoft.com/en-us/library/ee728598.aspx#choosing_synchronous_or_asynchronous_action_methods para más información. Básicamente, a lo que se reduce ese vínculo es que si no puede usar puertos de E/S de finalización para sus operaciones asincrónicas, es muy poco probable que vea un mejor rendimiento.

El segundo problema es que ASP.NET MVC toma un bloqueo de sesión en todas las solicitudes. Múltiples solicitudes dentro de una única sesión siempre serán serializadas, ya que de lo contrario la sesión del usuario podría corromperse si un controlador escribe en Session cuando otro controlador intenta leerlo. Ver http://forums.asp.net/t/1501623.aspx para contexto y una solución. MVC 2 Futures tiene una forma de desactivar este bloqueo; también puede estar incluido en MVC 3 propiamente dicho. Consulte https://blogs.msdn.com/b/rickandy/archive/2009/12/17/session-less-mvc-controller.aspx para obtener más información al respecto.

+2

¿Sigue siendo cierto usar asincrónico y esperar? – Dave

3

Acutally el problema radica en this.HttpContext.Session, porque está siendo bloqueado, si está escribiendo nada a una sesión en su AsyncController, se debe evitar el uso y this.HttpContext.Application - esto soluciona el problema , Tuve el mismo problema, y ​​pruébenos

+1

Esto está mal. HttpContext.Application 'Permite compartir información global entre múltiples sesiones y solicitudes dentro de una aplicación ASP.NET. Eso no es lo mismo que la Sesión. –

Cuestiones relacionadas