quartz net mvc hand fire asp asp.net multithreading iis background-process

asp.net - net - ¿Puedo usar hilos para llevar a cabo trabajos de larga ejecución en IIS?



quartz asp net (10)

¿Puedes crear un servicio de Windows para hacer esa tarea? Luego, use .NET remoto desde el Servidor Web para llamar al Servicio de Windows para que realice la acción. Si ese es el caso, eso es lo que haría.

Esto eliminaría la necesidad de retransmitir en IIS, y limitaría parte de su poder de procesamiento.

Si no, entonces forzaría al usuario a sentarse allí mientras el proceso está hecho. De esta forma, se asegura de que IIS lo complete y no lo mate.

En una aplicación ASP.Net, el usuario hace clic en un botón en la página web y esto crea una instancia de un objeto en el servidor a través del controlador de eventos y llama a un método en el objeto. El método se va a un sistema externo para hacer cosas y esto podría tomar un tiempo. Entonces, lo que me gustaría hacer es ejecutar esa llamada de método en otro hilo para que pueda devolver el control al usuario con "Su solicitud ha sido enviada". Estoy razonablemente feliz de hacer esto como "olvidar y olvidar", aunque sería aún más agradable si el usuario pudiera seguir sondeando el objeto para ver su estado.

Lo que no sé es si IIS permite que mi subproceso siga en ejecución, incluso si la sesión de usuario expira. Imagínese, el usuario dispara el evento e instanciamos el objeto en el servidor y disparamos el método en un nuevo hilo. El usuario está contento con el mensaje "Su solicitud ha sido enviada" y cierra su navegador. Eventualmente, esta sesión de usuarios finalizará en IIS, pero el hilo aún puede estar ejecutándose y funcionando. ¿IIS permitirá que el hilo siga ejecutándose o lo matará y eliminará el objeto una vez que expire la sesión del usuario?

EDITAR: a partir de las respuestas y los comentarios, entiendo que la mejor manera de hacerlo es mover el procesamiento de larga ejecución fuera de IIS. Además de todo lo demás, se trata del problema de reciclaje de dominios de aplicaciones. En la práctica, necesito lanzar la versión 1 en un tiempo limitado y tengo que trabajar dentro de un marco existente, por lo que me gustaría evitar la capa de servicio, de ahí el deseo de simplemente desconectar el hilo dentro de IIS. En la práctica, el "funcionamiento prolongado" aquí solo durará unos minutos y la concurrencia en el sitio web será baja, por lo que debería estar bien. Pero, la próxima versión definitivamente necesitará dividirse en una capa de servicio separada.


Aquí hay un buen hilo y código de muestra: http://forums.asp.net/t/1534903.aspx?PageIndex=2

Incluso jugué con la idea de llamar a una página de keep alive en mi sitio web desde el hilo para ayudar a mantener el grupo de aplicaciones con vida. Tenga en cuenta que si utiliza este método, necesita un manejo de recuperación realmente bueno, ya que la aplicación podría reciclarse en cualquier momento. Como muchos han mencionado, este no es el enfoque correcto si tiene acceso a otras opciones de servicio, pero para el alojamiento compartido esta puede ser una de sus únicas opciones.

Para mantener vivo el grupo de aplicaciones, puede realizar una solicitud a su propio sitio mientras se procesa el hilo. Esto puede ayudar a mantener vivo el grupo de aplicaciones si el proceso se ejecuta durante un tiempo prolongado.

string tempStr = GetUrlPageSource("http://www.mysite.com/keepalive.aspx"); public static string GetUrlPageSource(string url) { string returnString = ""; try { Uri uri = new Uri(url); if (uri.Scheme == Uri.UriSchemeHttp) { HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri); CookieContainer cookieJar = new CookieContainer(); req.CookieContainer = cookieJar; //set the request timeout to 60 seconds req.Timeout = 60000; req.UserAgent = "MyAgent"; //we do not want to request a persistent connection req.KeepAlive = false; HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); Stream stream = resp.GetResponseStream(); StreamReader sr = new StreamReader(stream); returnString = sr.ReadToEnd(); sr.Close(); stream.Close(); resp.Close(); } } catch { returnString = ""; } return returnString; }


Comenzamos por este camino, y realmente funcionó bien cuando nuestra aplicación estaba en un servidor. Cuando queríamos escalar a varias máquinas (o utilizar w3wp múltiples en un garen web) tuvimos que volver a evaluar y ver cómo administrar una cola de trabajo, manejo de errores, reintentos y el difícil problema de bloquear correctamente para asegurar que solo uno el servidor recoge el siguiente artículo.

... nos dimos cuenta de que no estamos en el negocio de escribir motores de procesamiento en segundo plano, por lo que buscamos soluciones existentes y aterrizamos utilizando el impresionante proyecto hangfire proyecto OSS

Sergey Odinokov ha creado una verdadera joya con la que es realmente fácil empezar, y le permite cambiar el proceso de mantenimiento y cola de trabajo. Hangfire utiliza subprocesos en segundo plano, pero persiste en los trabajos, maneja los reintentos y le proporciona visibilidad de la cola de trabajos. Así que los trabajos de hangfire son robustos y sobreviven a todos los caprichos de los dominios que se reciclan, etc.

Su configuración básica utiliza el servidor sql como almacenamiento, pero puede cambiarse para Redis o MSMQ cuando llegue el momento de escalar. También tiene una interfaz de usuario excelente para visualizar todos los trabajos y su estado, además de permitirle volver a poner trabajos en cola.

Mi punto es que si bien es completamente posible hacer lo que se desea en un hilo de fondo, hay mucho trabajo para que sea escalable y robusto. Está bien para cargas de trabajo simples, pero cuando las cosas se vuelven más complejas, prefiero usar una biblioteca especialmente diseñada en lugar de pasar por este esfuerzo.

Para obtener más información sobre las opciones disponibles, consulte el blog Scott Hanselman, que abarca algunas opciones para el manejo de trabajos en segundo plano en asp.net. (Le dio a hangfire una brillante crítica)

También, como lo menciona John, vale la pena leer el blog de Phil Haack sobre por qué el enfoque es problemático y cómo dejar de trabajar con gracia en el hilo cuando se descarga el dominio de aplicación.


No estoy de acuerdo con la respuesta aceptada.

Usar un hilo de fondo (o una tarea, comenzada con Task.Factory.StartNew ) está bien en ASP.NET. Al igual que con todos los entornos de alojamiento, es posible que desee comprender y cooperar con las instalaciones que rigen el cierre.

En ASP.NET, puede registrar el trabajo que necesita detenerse HostingEnvironment.RegisterObject al apagar usando el método HostingEnvironment.RegisterObject . Vea este artículo y los comentarios para una discusión.

En cuanto al tema general que a menudo escuchas de que es una mala idea, considera la alternativa de implementar un servicio de Windows (u otro tipo de aplicación de proceso adicional):

  • No más implementación trivial con despliegue web
  • No se puede implementar solo en los sitios web de Azure
  • Dependiendo de la naturaleza de la tarea en segundo plano, es probable que los procesos tengan que comunicarse. Eso significa que alguna forma de IPC o el servicio tendrá que acceder a una base de datos común.

Tenga en cuenta también que algunos escenarios avanzados incluso pueden necesitar que el hilo de fondo se ejecute en el mismo espacio de direcciones que las solicitudes. Veo el hecho de que ASP.NET puede hacer esto como una gran ventaja que se ha hecho posible a través de .NET.


No le conviene usar un hilo del grupo de subprocesos de IIS para esta tarea porque dejaría ese subproceso incapaz de procesar solicitudes futuras. Podrías buscar en Asynchronous Pages en ASP.NET 2.0 , pero tampoco sería la respuesta correcta. En cambio, lo que parece que se beneficiaría de usted es buscar en Microsoft Message Queuing . Esencialmente, agregaría los detalles de la tarea a la cola y otro proceso en segundo plano (posiblemente un Servicio de Windows) se encargaría de llevar a cabo esa tarea. Pero la conclusión es que el proceso en segundo plano está completamente aislado de IIS.


Parece que hay una forma compatible de hospedar el trabajo de larga duración en IIS. Los Servicios de flujo de trabajo parecen diseñados para esto, especialmente en conjunto con Windows Server AppFabric . El diseño permite el reciclaje de grupos de aplicaciones al admitir la persistencia automática y la reanudación del trabajo de larga duración.


Puede ejecutar tareas en segundo plano y se completarán incluso después de que finalice la solicitud. No permita que se arroje una excepción no detectada . Normalmente quieres arrojar siempre tus excepciones. Si se lanza una excepción en un nuevo hilo, se bloqueará el proceso de trabajo de IIS - w3wp.exe , porque ya no se encuentra en el contexto de la solicitud. Eso también va a matar cualquier otra tarea en segundo plano que tenga en ejecución, además de las sesiones respaldadas en memoria durante el proceso si las está usando. Esto sería difícil de diagnosticar, por lo que se desaconseja la práctica.


Puedes lograr lo que quieres, pero generalmente es una mala idea. Varios motores ASP.NET y CMS adoptan este enfoque, ya que desean instalarse en un sistema de alojamiento compartido y no tomar una dependencia de un servicio de Windows que deba instalarse. Por lo general, inician un hilo de larga ejecución en Global.asax cuando se inicia la aplicación, y hacen que ese subproceso procese las tareas en cola.

Además de reducir los recursos disponibles para IIS / ASP.NET para procesar solicitudes, también tiene problemas con la eliminación del hilo cuando se recicla el dominio de la aplicación, y luego tiene que lidiar con la persistencia de la tarea mientras está en vuelo, como así como comenzar el trabajo de respaldo cuando el AppDomain vuelve a funcionar.

Tenga en cuenta que, en muchos casos, AppDomain se recicla automáticamente en un intervalo predeterminado, así como si actualiza el archivo web.config, etc.

Si puede manejar la persistencia y los aspectos transaccionales de su hilo que se mata en cualquier momento, entonces puede sortear el reciclaje de AppDomain teniendo algún proceso externo que haga una solicitud en su sitio en algún intervalo, de modo que si el sitio se recicla usted están garantizados para que vuelva a iniciarse automáticamente en X minutos.

De nuevo, esto es típicamente una mala idea.

EDITAR: Aquí hay algunos ejemplos de esta técnica en acción:

Servidor de la comunidad: usar los servicios de Windows frente al hilo de fondo para ejecutar el código en intervalos programados Crear un hilo de fondo cuando el sitio web comienza por primera vez

EDITAR (del futuro lejano) - En estos días usaría hangfire .


Simplemente cree un proceso sustituto para ejecutar las tareas asíncronas; no tiene por qué ser un servicio de Windows (aunque ese es el enfoque más óptimo en la mayoría de los casos. MSMQ es muy difícil de matar.


Sugeriría usar hangfire para tales requisitos. Es un buen fuego y olvida el motor se ejecuta en segundo plano, es compatible con una arquitectura diferente, confiable porque está respaldado por el almacenamiento de persistencia.