2010-09-25 21 views
6

Quiero poner en práctica esa lógica en mi aplicación asp-net-mvc:ASP.NET MVC multihilo

user clicks a button ->

server executes some time-consuming logic in ~15 threads (i get data from really slow independent sources) ->

when all work is done, server merges the results and passes it back to user 

El otro día que he vi un artículo que explicaba por qué no se recomienda crear nuevos subprocesos en la aplicación asp-net, y ThreadPool es el que debería usarse. ¿Cuáles son las mejores prácticas para mvc en este caso? ¿Por qué no debería crear mis hilos, trabajadores de fondo, tareas, lo que sea y usar threadpool? La aplicación se alojará en un servidor público, si es importante.

Respuesta

4

Si está utilizando .Net 4, incluso recomendaría mirar los espacios de nombres paralelos. Lo hacen aún más simple y hacen un mejor trabajo al utilizar todos sus núcleos de CPU.

También me gustaría descargar esto de su aplicación web principal por completo. Tener un conjunto separado de servicios o una cola de mensajes para manejar esta solicitud de larga ejecución le permitirá escalar mucho más fácilmente y le permitirá a su aplicación web preocuparse por el mantenimiento de las solicitudes de página, sin ejecutar la lógica de ejecución prolongada. Busque algo como "solicitud larga de ejecución" para comenzar.

3

Debido a que un ThreadPool está diseñado para hacer eso:

Proporciona un grupo de subprocesos que se pueden utilizar para ejecutar tareas, elementos de trabajo posterior, asíncrono proceso de E/S, espera en nombre de otros hilos, y temporizadores de proceso.

Supongo que es mejor almacenar los resultados en su servidor en una base de datos cuando hayan terminado.

Y luego podría utilizar un temporizador y AJAX para solicitar periódicamente si el proceso está hecho, de ser así, obtener datos.

3

No debe crear sus propios subprocesos porque esto tiene una sobrecarga significativa. Crear un nuevo hilo es costoso. Entonces la pregunta debería ser: ¿por qué no deberías usar el threadpool? Tiene una cantidad de hilos listos para usar. Un enfoque aún mejor sería utilizar la biblioteca paralela de tareas, que proporciona una capa de abstracción por encima del grupo de subprocesos que facilita mucho el trabajo con subprocesos.

Debe tener en cuenta que la única forma (fácil) de lograr esto es haciendo que el usuario espere hasta que todo el trabajo esté hecho y luego sirva la página. Un enfoque más complicado pero también más receptivo sería usar Ajax (a través de jQuery, por ejemplo) para preguntarle al servidor periódicamente cuánto ha progresado el trabajo. De esta manera también puede proporcionar algún indicador de progreso.

+0

Este sería una operación llevada a cabo por el administrador/moderador, por lo que no es necesario :) –

6

Sí JQuery y algunos AJAX lo harán de la forma más adecuada. Cargue la página, luego envíe ~ 15 consultas Ajax separadas de vuelta al Servidor y déjelos terminar de forma asincrónica. De esta forma, puede dejar que el servidor web maneje Threading (lo cual funciona bien) y concéntrese en mostrar un ticker o una barra de progreso virtual al usuario mientras espera.

+2

Mientras el trabajo se pueda dividir de esta manera, entonces este es un enfoque muy bueno ... además de evitar las trampas de tirar tu propio hilos, es mucho más fácil dar retroalimentación al usuario a medida que avanza. –

+2

Si este es un buen enfoque depende de si desea fusionar los resultados en el servidor o en el cliente. Existe el riesgo de que necesite mover mucha lógica al cliente que podría manejarse mejor en el servidor. –

+0

esto parece una solución fácil al principio, sin embargo, si su cliente tiene la misma URL abierta en diferentes pestañas, notará muy rápidamente las limitaciones de las conexiones abiertas a un único dominio por navegador. (algo que mucha gente está descubriendo ahora con websockets) También redujo el número de solicitudes que su servidor puede manejar a 1/15 en comparación con lo que Jim Leonardo propuso. La respuesta de Rohan Singh es menos compleja, y solo ligeramente menos escalable que el – Cohen

7

Este parece ser un muy buen lugar para usar el nuevo AsycController en ASP.NET MVC 2. Es realmente fácil de usar y le permite ejecutar consultas en múltiples fuentes independientes sin bloquear los hilos de solicitud.

MSDN has a great example donde están consultando un servicio de noticias, un servicio meteorológico y un servicio de deportes.

Se puede ver en el código original que se está consultando de forma secuencial fuente, pero en la versión final, todas las tareas se ejecutan en los retornos paralelos y de control al controlador cuando están todos completos:

public void IndexAsync(string city) 
{ 
    AsyncManager.OutstandingOperations.Increment(3); 

    NewsService newsService = new NewsService(); 
    newsService.GetHeadlinesCompleted += (sender, e) => 
    { 
     AsyncManager.Parameters["headlines"] = e.Value; 
     AsyncManager.OutstandingOperations.Decrement(); 
    }; 
    newsService.GetHeadlinesAsync(); 

    SportsService sportsService = new SportsService(); 
    sportsService.GetScoresCompleted += (sender, e) => 
    { 
     AsyncManager.Parameters["scores"] = e.Value; 
     AsyncManager.OutstandingOperations.Decrement(); 
    }; 
    sportsService.GetScoresAsync(); 

    WeatherService weatherService = new WeatherService(); 
    weatherService.GetForecastCompleted += (sender, e) => 
    { 
     AsyncManager.Parameters["forecast"] = e.Value; 
     AsyncManager.OutstandingOperations.Decrement(); 
    }; 
    weatherService.GetForecastAsync(); 
} 

public ActionResult IndexCompleted(string[] headlines, string[] scores, string[] forecast) 
{ 
    return View("Common", new PortalViewModel { 
     NewsHeadlines = headlines, 
     SportsScores = scores, 
     Weather = forecast 
    }); 
} 
+0

de Jim. Ese enlace ahora está roto – PandaWood

+0

Maldición, una URL debería ser una promesa, especialmente en algo como la documentación. También es molesto que la URL solo haya cambiado trivialmente (agregando "(vs = v.100)" sin ninguna razón obvia). De todos modos, gracias por señalarlo, @PandaWood. Corregido ahora. –

+0

Esto está desactualizado ya que los controladores MVC 4+ incluyen la funcionalidad Async. Aquí hay un ejemplo: http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4 –