2012-03-28 12 views
6

Tengo una aplicación ASP.NET MVC3 que maneja procesos que consumen tiempo (copiando un archivo grande de la red). Lo que queremos hacer es:Manejo de solicitud de Async en ASP.NET MVC

  1. usuario hace clic en un botón para enviar el formulario para desencadenar el proceso
  2. aplicación se inicia un nuevo hilo para empezar a copiar el archivo
  3. aplicación muestra un mensaje diciendo que el archivo-copia proceso ha comenzado
  4. El usuario puede cerrar el navegador mientras la copia se procesa y termina en segundo plano.

La idea es que el usuario no necesita ninguna confirmación sobre el progreso del proceso, ni se le notifica cuando el proceso se ha completado.

Actualmente, permitimos que el controlador active un evento en un Servicio de Windows y utilice el Servicio de Windows para realizar el trabajo real. Me pregunto si hay una forma mejor/más limpia de hacer esto.

+3

Para MVC 3, consulte mi artículo de MSDN: http://msdn.microsoft.com/en-us/library/ee728598(VS.98).aspx Si puede usar MVC 4 y Developer Express 11, estoy escribiendo un nuevo tutorial Async/MVC que es mucho más simple. – RickAndMSFT

Respuesta

6

Puede usar System.Threading.Tasks.Task llamando al método StartNew con un Action delegate.

El uso de esas herramientas que su controlador sería algo como esto:

[HttpPost] 
public ActionResult DoSomethingLongRunning() 
{ 
    if (ModelState.IsValid) 
    { 
     Task.Factory.StartNew(() => 
        fileCopier.CopyFile(CopyFileParameter1, CopyFileParameter2)); 

     return RedirectToAction("View Indicating Long Running Progress"); 
    } 
    else 
    { 
     // there is something wrong with the Post, handle it 
     return View("Post fallback view"); 
    } 
} 

Otra opción es que podría utilizar System.Reactive.Concurrency y la interfaz IScheduler con TaskPoolScheduler como la aplicación concreta para realizar la acción (posiblemente inyecta en el constructor del controlador .

public ActionResult DoSomethingLongRunning() 
{ 
    if (ModelState.IsValid) 
    { 
     ISchedulerImplementation.Schedule(new Action(() => 
     { 
      fileCopier.CopyFile(CopyFileParameter1, CopyFileParameter2); 
     })); 
     return RedirectToAction("View Indicating Long Running Progress"); 
    } 
    else 
    { 
     // there is something wrong with the Post, handle it 
     return View("Post fallback view"); 
    } 
} 

como beneficio, si lo haces de esta manera se puede utilizar TestScheduler como la implementación de la interfaz cuando se está probando la unidad.

+0

Esa puede ser una alternativa, pero no es la mejor solución en este caso. Debido a que el usuario no necesita ser notificado acerca de la finalización del proceso desencadenado, esto puede aislarse por completo en un servicio de Windows, lo que garantiza que funciona incluso si el servidor web deja de funcionar. –

3

Creo que tener el Servicio de Windows alojar su proceso de larga duración es la mejor opción. Si está hospedado por IIS, siempre se arriesga a que el grupo de aplicaciones que está ejecutando muera por inactividad.

Una posibilidad relacionada es alojar un servicio WCF dentro de su servicio de Windows y proporcionar un HTTP externo u otro endpoint para el servicio. De esa manera, su interfaz web puede llamar a un método de contrato de "inicio" de su servicio WCF, y potencialmente a otros métodos si es necesario.

+0

Una buena respuesta, alojar todo en IIS (incluso bajo un grupo de aplicaciones diferente) create no aísla el proceso y no lo hace independiente. Si IIS se detiene, todo se detiene. También eche un vistazo a este enlace sobre las diferencias entre el alojamiento bajo IIS o en un servicio de Windows: http://social.msdn.microsoft.com/Forums/en/wcf/thread/015d711d-ce5a-46a1-a93e-1c68746e76d3 –

2

Voy a publicar una solicitud a un servicio WCF MSMQ alojado en IIS 7 WAS. Hay an awesome article cómo configurarlo.

Las tareas de ejecución prolongada que utilizan recursos externos tienen un alto riesgo de error. El error más grande que los desarrolladores suelen cometer es suponer que el hardware y las redes tienen una capacidad ilimitada y son muy confiables. A menudo no es.

Puede ser problemático, incluso catastrófico, si el proceso prolongado se interrumpe por la pérdida momentánea de la conectividad de la red o si se reinicia el servidor remoto. Si su proceso de ejecución prolongada incluye procesamiento adicional, como descomprimir el archivo o analizarlo, puede correr un mayor riesgo de falla si no hay suficiente memoria para realizar el procesamiento. Los usuarios pueden enviar demasiadas solicitudes y no hay suficientes recursos disponibles para manejar los problemas concurrentes. Si permite que su aplicación ASP.NET MVC realice el procesamiento a través del async controllers, entonces se sorprenderá cuando se interrumpa su proceso de larga ejecución cuando IIS recicla el proceso de trabajo.

MSMQ 4 hace un buen trabajo para mitigar estos riesgos. Si el proceso falla, puede intentarlo un par de veces antes de darse por vencido. Puede aprender a configurarlo here. Puede usar application specific deadletter queues para manejar el caso donde el proceso falló después de una cantidad de intentos aceptables. Esto es importante para el personal operativo para diagnosticar problemas. También puede usar este esquema para notificar a un usuario por correo electrónico que el proceso falló (o tuvo éxito), incluso si la máquina desde la que se originó la solicitud está apagada.

Alojarlo en IIS en lugar de un servicio de Windows ofrece capacidades adicionales. Por ejemplo, el proceso de trabajo de IIS se puede reciclar si se estanca o excede un umbral de memoria. Esto último puede ser un problema cuando está usando algún código nativo para realizar el procesamiento. Puede reciclarlo cada cuatro (elija su marco de tiempo) horas. Esto último es bastante importante cuando se trabaja con grandes cantidades de memoria administrada porque con el tiempo la cabeza del objeto grande se fragmenta tanto que resulta casi imposible administrar la asignación de suficiente memoria para otra solicitud grande. Puede encontrar que un servicio WCF alojado en un Servicio de Windows puede sufrir este problema.

En realidad, depende de qué tan confiable sea el proceso de fondo. De lo contrario, el uso de WCF, MSMQ e IIS puede ser excesivo.

Cuestiones relacionadas