c# .net asp.net multithreading iis-5

c# - Cómo saber quién mata mis hilos.



.net asp.net (15)

Tengo un hilo que simplemente está desapareciendo ... me gustaría saber quién está matando mi hilo y por qué.

Se me ocurre que el sistema operativo está matando a mi hilo, pero me gustaría confirmarlo y, si es posible, saber por qué lo está matando.

En cuanto al hilo, puedo afirmar que tiene al menos 40 minutos de ejecución antes de morir, pero de repente muere alrededor de 5 minutos.

public void RunWorker() { Thread worker = new Thread(delegate() { try { DoSomethingForALongLongTime(); } catch(Exception e) { //Nothing is never logged :( LogException(e); throw e; } }); worker.IsBackground = true; worker.SetApartmentState(System.Threading.ApartmentState.STA); worker.Start(); }

EDITAR: abordar respuestas

  • Probar / atrapar posibles excepciones:
    Está implementado y no atrapa nada :(
  • Rosca principal muriendo:
    Este hilo es creado por el servidor web, que continúa ejecutándose
  • Finalización del trabajo:
    El trabajo no se ha completado, ya que finalmente afecta a la base de datos, puedo verificar si se ha hecho o no cuando el hilo muere.

Habiendo pensado en estas cosas me trajo a esta pregunta, ¿quién está matando mis hilos?

PD. No es Lady Goldent en la sala con el palo de vela :)


Cuando llama a RunWorker (), puede agregar una referencia a su hilo a una lista. Una vez que haya detectado que su hilo ha muerto, puede inspeccionar el estado del hilo, tal vez revelará cómo murió. O, quizás no haya muerto, simplemente está esperando algún recurso (como la conexión a la base de datos).

List runningThreads = ... public void RunWorker() { Thread worker = new Thread(delegate() .. runningThreads.add(worker); worker.Start(); } public void checkThreads() { for (Thread t : runningThreads) { Console.WriteLine("ThreadState: {0}", t.ThreadState); } }


Debes instrumentar DoSomethingForALongLongTime () con muchos registros de depuración, para que puedas averiguar en qué punto deja de ejecutarse el código. O adjunte un depurador y descifre todas las excepciones de primera oportunidad.


El proceso podría estar terminando. Eso sería lo que worker.IsBackground = true; está diseñado para hacerlo, mata tu hilo cuando el hilo principal sale.



No sé la respuesta, pero algunos pensamientos:

  • ¿Podría estar lanzando una excepción? ¿Ha intentado poner un try / catch alrededor de la llamada DoSomethingForALongLongTime ()?
  • ¿Hay puntos donde sale normalmente? Intenta poner algo de registro en ellos.
  • ¿Obtiene el mismo comportamiento dentro y fuera del depurador? ¿La ventana de salida en el depurador proporciona alguna sugerencia?

ACTUALIZAR

Tu dijiste:

Este hilo es creado por el servidor web, que continúa ejecutándose

Si el subproceso se está ejecutando dentro de asp.net, es posible que el subproceso se esté eliminando cuando el proceso de trabajo de asp.net se recicle, lo que se hará periódicamente. Podría intentar apagar el proceso de reciclaje del trabajador y ver si eso hace alguna diferencia.


Podría estar lanzando una de las varias excepciones incomprensibles, incluyendo Desbordamiento de pila o Sin memoria . Estas son las excepciones más difíciles de rastrear.

¿Cómo se ve el consumo de memoria mientras este hilo se está ejecutando? ¿Puedes usar un generador de perfiles de memoria para ver si está fuera de control? ¿Puedes agregar algo de registro en bucles internos? Si tiene un método recursivo, agregue un contador y lance una excepción si se repite un número imposible de veces. ¿Está utilizando objetos grandes que podrían estar causando una gran fragmentación de la pila de objetos (causa errores de falta de memoria incluso cuando no está realmente fuera)?


Puede intentar aumentar el valor de tiempo de ejecución de la configuración / system.web / httpRuntime en web.config (el valor predeterminado es 110 segundos en .NET 4.0 y 90 en corresponde a http://msdn.microsoft.com/en-us/library/e1f13641.aspx ). Puede intentar cambiarlo dinámicamente Server.ScriptTimeout = 300 (consulte http://www.beansoftware.com/ASP.NET-Tutorials/Long-Operations.aspx ). Si este parámetro no ayuda, entonces creo que tiene otro problema como el reciclaje de subprocesos desde IIS. La forma en que puede ver el valor predeterminado de este parámetro es mucho menor que el tiempo de vida típico de su hilo. Creo que tu problema tiene otra naturaleza, pero para estar seguro ...

¿Por qué establece el estado del apartamento para el hilo? ¿Qué objetos COM usas en el hilo de trabajo? ¿Tiene un código no administrado que hace el mayor trabajo posible donde también puede insertar algún código? Creo que deberías tener más información sobre SomethingForALongLongTime para poder resolver el problema.

Y una sugerencia más. ¿Podría insertar una línea de código después de llamar a SomethingForALongLongTime(); para estar seguro, que SomethingForALongLongTime no termina sin una excepción?

ACTUALIZADO: Para estar absolutamente seguro de que IIS no eliminará tu hilo, puedes intentar crear un proceso que haga SomethingForALongLongTime(); En lugar de utilizar hilos.


Si la comprobación de una excepción no muestra nada útil, haga que su código de hilo escriba en un archivo de registro en los puntos clave. Entonces podrás ver exactamente cuándo deja de funcionar y, con suerte, por qué.


Su edición revela la respuesta:

Es el servidor web de mayordomo .

¿Cómo exactamente alojas estos hilos? Un entorno de servidor web no está diseñado exactamente para alojar procesos de larga duración. De hecho, es probable que esté configurado para detener sitios fuera de control, ¿cada 40 minutos tal vez?

Editar:
Para una solución rápida, su mejor oportunidad es establecer worker.IsBackground = false; porque la configuración actual de true permite que el sistema elimine el subproceso principal sin esperar su bgw.

En otra nota, no tiene sentido usar un BackgroundWorker en una aplicación ASP.NET, está destinado a WinForms y WPF. Sería mejor crear un subproceso separado para esto, ya que está cambiando algunas de las propiedades de los subprocesos. Eso no se recomienda para un hilo ThreadPool (Bgw).


Tu hilo probablemente acaba de lanzar una excepción. Intente colocar un bloque try / catch en torno a DoSomethingForALongLongTime y ver qué recoge.

Actualización: no noté antes que comenzabas desde un servidor web. Eso puede ser una muy mala idea. En particular, ¿el hilo separado utiliza alguna información derivada de HttpContext.Current ? Eso incluiría Request , Response , Session , etc., así como cualquier información de la página.

Esto es malo porque estas cosas solo duran mientras dure la solicitud. Una vez que se termina la solicitud, se vuelven inválidas, por decir lo menos.

Si necesita iniciar un hilo de larga duración desde una aplicación web o servicio web, debe crear un servicio de Windows simple y alojar un servicio WCF dentro de él. Haga que la página web luego envíe toda la información necesaria para realizar la tarea al servicio. El servicio puede incluso utilizar MSMQ como transporte, lo que garantizará que no se pierdan mensajes, incluso si el servicio está ocupado.


Un subproceso en segundo plano solo se ejecutará mientras haya subprocesos en primer plano.

Tan pronto como terminen todos los subprocesos de primer plano, se abortará cualquier subproceso de fondo que todavía esté en ejecución.


Una forma potencial de obtener más información: adjunte un depurador y rompa en la terminación del hilo. Dependiendo de cómo se termine su hilo, esto podría no funcionar.

  1. Descarga Debugging Tools para Windows si aún no lo tienes
  2. Ejecute windbg.exe, adjunte a su proceso
  3. Irrumpir en windbg, escriba sxe et para habilitar la ruptura en la salida del hilo
  4. Cuando el depurador se rompe, inspeccione el estado del sistema, otros subprocesos, etc.
  5. Para obtener la pila administrada, cargue sos.dll ( .loadby sos mscorsvr , .loadby sos mscorwks , o .loadby sos clr debería funcionar), luego ejecute !clrstack (vea !help para otros comandos de sos)

Si obtienes mucho ruido de otros subprocesos que salen, ejecuta windbg para continuar después de romper si no es la ID del hilo lo que te interesa.

Editar: Si cree que el hilo se termina dentro de su proceso, también puede establecer un punto de interrupción en TerminateThread ( bp kernel32!TerminateThread ) y ExitThread ( bp kernel32!ExitThread ) para atrapar la pila del asesino.


Una respuesta simple sería: "El asesino no deja una tarjeta de identificación";)

  • Si su hilo está alojado en IIS, probablemente el hilo se elimine por el proceso del grupo de aplicaciones que se recicla. Es posible que el servidor continúe ejecutándose, pero el proceso que aloja tu elemento se detiene hasta que una nueva solicitud enciende todo de nuevo.
  • Si su hilo está alojado en un ejecutable, la única forma de matarlo es matándolo usted mismo, lanzando una excepción en el hilo o terminando el proceso host

Espero que esto ayude.


Varias personas (incluido yo here ) señalaron que hospedar un hilo de larga duración en IIS es una mala idea. Tu hilo se ejecutará dentro de un ''proceso de trabajo'' de IIS. Estos procesos son terminados (reciclados) periódicamente por IIS, lo que hará que su hilo se muera.

Le sugiero que intente desactivar el proceso de reciclaje de IIS para ver si eso marca una diferencia. Puedes encontrar más información here .


use AsyncTasks para lograr su trabajo de larga duración en asp.net