En una aplicación ASP.Net, el usuario hace clic en un botón en la página web y luego 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 pasa a un sistema externo para hacer cosas y esto puede llevar un tiempo. Entonces, lo que me gustaría hacer es ejecutar esa llamada al método en otro hilo para poder devolver el control al usuario con "Su solicitud ha sido enviada". Estoy razonablemente feliz de hacer esto como disparar y olvidar, aunque sería aún mejor si el usuario pudiera seguir sondeando el estado del objeto.
Lo que no sé es si IIS permite que mi hilo siga funcionando, incluso si la sesión del usuario expira. Imagínese, el usuario dispara el evento y nosotros instanciamos el objeto en el servidor y disparamos el método en un nuevo hilo. El usuario está satisfecho con el mensaje "Su solicitud ha sido enviada" y cierra su navegador. Eventualmente, esta sesión de usuarios expirará en IIS, pero es posible que el subproceso aún se esté ejecutando, 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: De las respuestas y comentarios, entiendo que la mejor manera de hacer esto es mover el procesamiento de larga duración fuera de IIS. Aparte de todo lo demás, se trata del problema de reciclaje del dominio de aplicación. En la práctica, necesito que la versión 1 despegue 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 disparar el hilo dentro de IIS. En la práctica, la "ejecución prolongada" aquí solo será de 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.
Respuestas:
Puedes lograr lo que quieras, pero normalmente es una mala idea. Varios motores de blogs y CMS ASP.NET adoptan este enfoque, porque quieren que se puedan instalar en un sistema de alojamiento compartido y no depender de un servicio de Windows que deba instalarse. Por lo general, inician un subproceso de larga duración en Global.asax cuando se inicia la aplicación, y ese proceso de subproceso pone en cola las tareas.
Además de reducir los recursos disponibles para IIS / ASP.NET para procesar solicitudes, también tiene problemas con la eliminación del subproceso cuando se recicla AppDomain, y luego tiene que lidiar con la persistencia de la tarea mientras está en curso, como así como comenzar el trabajo de nuevo cuando el AppDomain vuelva a funcionar.
Tenga en cuenta que, en muchos casos, AppDomain se recicla automáticamente en un intervalo predeterminado, así como si actualiza el web.config, etc.
Si puede manejar la persistencia y los aspectos transaccionales de la eliminación de su hilo en cualquier momento, entonces puede evitar el reciclaje de AppDomain mediante algún proceso externo que realice una solicitud en su sitio en algún intervalo, de modo que si el sitio se recicla, usted están garantizados para que se reinicie automáticamente en X minutos.
Una vez más, esto suele ser una mala idea.
EDITAR: Aquí hay algunos ejemplos de esta técnica en acción:
Servidor de la comunidad: uso de servicios de Windows frente a subprocesos en segundo plano para ejecutar código en intervalos programados Creación de un subproceso en segundo plano cuando se inicia el sitio web
EDITAR (desde un futuro lejano): estos días usaría Hangfire .
fuente
HostingEnvironment.RegisterObject
).QueueBackgroundWorkItem
para registrar fácilmente tareas en segundo plano, es posible que desee actualizar su respuesta nuevamente.No estoy de acuerdo con la respuesta aceptada.
Usar un hilo de fondo (o una tarea, comenzada
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 correctamente al apagar utilizando el
HostingEnvironment.RegisterObject
método. Vea este artículo y los comentarios para una discusión.(Como señala Gerard en su comentario, ahora también hay
HostingEnvironment.QueueBackgroundWorkItem
llamadas aRegisterObject
para registrar un programador para que el elemento de fondo funcione. En general, el nuevo método es mejor ya que se basa en tareas).En cuanto al tema general que a menudo escucha que es una mala idea, considere la alternativa de implementar un servicio de Windows (u otro tipo de aplicación de proceso adicional):
Tenga en cuenta también que algunos escenarios avanzados pueden incluso necesitar que el subproceso en segundo plano 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.
fuente
No querrá utilizar un hilo del grupo de hilos de IIS para esta tarea porque dejaría ese hilo sin poder procesar solicitudes futuras. Podría buscar páginas asincrónicas en ASP.NET 2.0 , pero esa tampoco sería la respuesta correcta. En cambio, parece que se beneficiaría de buscar en Microsoft Message Queue Server . Básicamente, agregaría los detalles de la tarea a la cola y otro proceso en segundo plano (posiblemente un servicio de Windows) estaría a cargo de llevar a cabo esa tarea. Pero la conclusión es que el proceso en segundo plano está completamente aislado de IIS.
fuente
Sugeriría usar HangFire para tales requisitos. Es un buen motor de disparo y olvido que se ejecuta en segundo plano, admite una arquitectura diferente y es confiable porque está respaldado por almacenamiento de persistencia.
fuente
Hay un buen hilo y código de muestra aquí: http://forums.asp.net/t/1534903.aspx?PageIndex=2
Incluso he jugado con la idea de llamar a una página de mantener vivo en mi sitio web desde el hilo para ayudar a mantener vivo el grupo de aplicaciones. Tenga en cuenta que si está utilizando este método, necesita un manejo de recuperación realmente bueno, porque 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 ayudar a 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 su proceso se ejecuta durante mucho tiempo.
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; }
fuente
Comenzamos por este camino, y realmente funcionó bien cuando nuestra aplicación estaba en un servidor. Cuando queríamos escalar horizontalmente a varias máquinas (o usar múltiples w3wp en una web garen) tuvimos que reevaluar y ver cómo administrar una cola de trabajo, manejo de errores, reintentos y el complicado problema de bloquear correctamente para asegurar solo una El servidor recoge el siguiente elemento.
... nos dimos cuenta de que no estamos en el negocio de escribir motores de procesamiento en segundo plano, así que buscamos soluciones existentes y aterrizamos utilizando el increíble proyecto OSS hangfire
Sergey Odinokov ha creado una verdadera joya con la que es realmente fácil comenzar y le permite intercambiar el backend de cómo el trabajo se persiste y se pone en cola. Hangfire utiliza subprocesos en segundo plano, pero conserva los trabajos, gestiona los reintentos y le brinda visibilidad de la cola de trabajos. Por lo tanto, los trabajos de hangfire son sólidos y sobreviven a todos los caprichos de los dominios de aplicaciones que se reciclan, etc.
Su configuración básica utiliza el servidor SQL como almacenamiento, pero puede cambiarlo por Redis o MSMQ cuando sea el momento de escalar. También tiene una excelente interfaz de usuario para visualizar todos los trabajos y su estado, además de permitirle volver a ponerlos en cola.
Mi punto es que si bien es completamente posible hacer lo que quieras en un hilo en segundo plano, hay mucho trabajo para hacerlo 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 realizar este esfuerzo.
Para obtener más perspectiva sobre las opciones disponibles, consulte el blog de Scott Hanselman que cubre algunas opciones para manejar trabajos en segundo plano en asp.net. (Le dio a Hangfire una brillante reseña)
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 detener el trabajo en el hilo cuando se descarga el dominio de aplicación.
fuente
¿Puede crear un servicio de Windows para realizar esa tarea? Luego, use la comunicación remota .NET desde el servidor web para llamar al servicio de Windows para realizar 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 potencia de procesamiento.
De lo contrario, obligaría al usuario a sentarse allí mientras se realiza el proceso. De esa manera, se asegurará de que IIS lo complete y no lo elimine.
fuente
Parece haber una forma compatible de alojar trabajos de larga duración en IIS. Los servicios de flujo de trabajo parecen diseñados para esto, especialmente junto con Windows Server AppFabric . El diseño permite el reciclaje del grupo de aplicaciones al admitir la persistencia automática y la reanudación del trabajo de larga duración.
fuente
Puede ejecutar tareas en segundo plano y se completarán incluso después de que finalice la solicitud. No permita que se lance una excepción no detectada . Normalmente, siempre desea lanzar sus excepciones. Si se lanza una excepción en un nuevo hilo, bloqueará el proceso de trabajo de IIS, w3wp.exe , porque ya no se encuentra en el contexto de la solicitud. Eso también eliminará cualquier otra tarea en segundo plano que tenga en ejecución, además de las sesiones respaldadas por la memoria en proceso, si las está utilizando. Esto sería difícil de diagnosticar, por lo que se desaconseja la práctica.
fuente
Simplemente cree un proceso sustituto para ejecutar las tareas asincrónicas; no tiene que ser un servicio de Windows (aunque ese es el enfoque más óptimo en la mayoría de los casos. MSMQ está muy por encima de la eliminación).
fuente