2010-04-20 8 views
27

Tengo un hilo que está desterrando ... Me gustaría saber quién está matando mi hilo y por qué.Cómo saber quién mata a mis hilos

Se me ocurre que mi hilo está siendo destruido por el sistema operativo, pero me gustaría confirmar esto 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(); 
} 

EDIT: Abordar respuestas

  • try/catch posibles excepciones:
    se implementa y atrapa nada :(
  • Tema principal moribundos:
    Este hilo es creado por el servidor web , que continúa ejecutándose
  • Finalización del trabajo:
    El trabajo no se completa, ya que finalmente afecta t En la base de datos, puedo verificar si está hecho o no cuando el hilo muere.

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

ps. No es Lady Goldent en la sala de estar con el candelabro :)

+0

¿Se produce una excepción cuando se vetó el hilo, y si es así, ¿qué quiere decir? ¿Estás seguro de que el hilo no termina simplemente, lo que también explicaría su desaparición? –

+10

Esto podría representar un buen episodio de CSI. ;) – FrustratedWithFormsDesigner

+0

Si este ASP.NET y/o IIS, agrega esas etiquetas –

Respuesta

19

personas Varios (incluido yo mismo, here) señaló que la celebración de un hilo de larga duración en IIS es una mala idea. Su 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 muera.

que sugieren que intenta convertir-off IIS reciclaje de procesos de trabajo para ver si eso hace la diferencia. Puede encontrar más información here.

+0

Esto se ve muy prometedor; se adapta a todos los síntomas. Sin embargo, estoy sorprendido de que IIS pueda migrar todo el estado del subproceso a un subproceso sin que su función DoStuffForLongTime() ni siquiera lo note. ¿Es memoria compartida? – Justin

+0

porque esto es un hilo de fondo, no tiene que ejecutarse para siempre. una vez que finaliza el último hilo del primer plano del anfitrión, todo lo demás se va al sur ... No puedo decir si puedes engañar a IIS, pero simplemente cambiaría al primer plano y a la prueba. –

13

Probablemente, el hilo arrojó una excepción. Trata de poner un bloque try/catch alrededor del DoSomethingForALongLongTime y observa qué es lo que acelera.


Actualización: no me di cuenta antes de que usted comenzaba esto desde un servidor web. Esa puede ser una muy mala idea. En particular, ¿el hilo separado utiliza cualquier 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 la solicitud termina, se vuelven inválidos, por decir lo menos.

Si necesita iniciar un hilo de larga ejecució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 envíe toda la información necesaria para realizar la tarea al servicio. El servicio puede incluso usar MSMQ como transporte, lo que asegurará que no se pierda ningún mensaje, incluso si el servicio se vuelve ocupado.

+0

implementado, sin suerte :( – mcabral

+0

Tal vez el hilo hizo algo completamente ilegal y murió a la segmentación violación (que no se muestran como una excepción). Es posible crear un manejador de señales que plantea un indicador de error, que luego se puede comprobar. – Justin

+0

@Justin : está ejecutando .NET. No hay nada tan completamente ilegal que no haya ninguna excepción. Un "segmento viola" ción "no puede ocurrir, a menos que trabaje con código no administrado. –

3

El proceso puede estar finalizando. Eso sería lo que worker.IsBackground = true; está diseñado para hacer, matar a su hilo cuando sale el hilo principal.

2

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

+0

Tenía la misma ideia. Tal vez alguna condición esté finalizando el hilo, por lo que ... –

3

Un hilo de fondo solo se ejecutará mientras haya hilos de primer plano runnnig.

Tan pronto como finalicen todos los hilos de primer plano, cualquier hebra de fondo que siga ejecutándose se cancelará.

4

No sé la respuesta, pero algunos pensamientos:

  • no podía ser una excepción? ¿Has intentado poner/probar la llamada DoSomethingForALongLongTime()?
  • ¿Hay algún punto donde sale normalmente? Intenta poner algo de registro en ellos.
  • ¿Obtienes el mismo comportamiento dentro y fuera del depurador? ¿La ventana de salida en el depurador proporciona alguna pista?

ACTUALIZACIÓN

Usted dijo:

Este hilo es creado por el servidor web , que continúa funcionando

Si el hilo se ejecuta dentro de ASP. neto, entonces, es posible que el hilo esté siendo eliminado cuando el proceso de trabajo de asp.net se recicla, lo que hará periódicamente. Podría intentar desactivar el reciclaje de procesos de trabajo y ver si eso hace alguna diferencia.

+0

Plausible. Un buen resumen está disponible aquí: http://bluedragon.blog-city.com/why_might_a_net_web_application_app_domain_restart_the_reaso.htm –

4

Tu edición revela la respuesta:

Es el servidor web Mayordomo .

¿Cómo aloja exactamente estos hilos? Un entorno de servidor web no está diseñado exactamente para alojar procesos de larga vida. De hecho, probablemente esté configurado para detener sitios fugitivos, ¿quizás cada 40 minutos?

Editar:
Para una solución rápida, la mejor posibilidad es fijar worker.IsBackground = false; porque su configuración actual de la verdadera permite que el sistema para matar al padre hilos w/o la espera de su bgw.

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

+1

+1. El trabajo "LongLong" probablemente deba descargarse a una aplicación/servicio dedicado. – Audrius

2

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

  • Si el hilo está alojado en IIS, probablemente, el hilo es matado por el proceso de grupo de aplicación que recicla. Es posible que el servidor continúe ejecutándose, pero el proceso que aloja el elemento se detiene hasta que una nueva solicitud lo reinicie todo de nuevo.
  • Si el hilo está alojado en un ejecutable, la única forma en que puede ser matado es matando al hilo de ti mismo, lanzar una excepción en el hilo o terminar el proceso de host

Espero que esto ayude.

2

Puede intentar aumentar executionTimeout valor de 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). Es este parámetro no ayuda, entonces creo que tienes un problema como el reciclaje de subprocesos de IIS. Cómo puede ver el valor predeterminado de este parámetro es mucho menos que el típico tiempo en vivo de su hilo. Creo que su problema tiene otra naturaleza, pero para estar seguro ...

¿Por qué se 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 la mayor parte del trabajo donde también puede insertar algún código? Creo que debería tener más información sobre SomethingForALongLongTime para poder resolver el problema.

Y una pequeña sugerencia más. ¿Podría insertar una línea de código después de llamar al SomethingForALongLongTime(); para asegurarse de que SomethingForALongLongTime no termine sin una excepción?

ACTUALIZADO: Para estar absolutamente seguro de que su hilo no será eliminado por IIS, puede intentar crear un proceso que haga SomethingForALongLongTime(); en lugar de usar hilos.

1

Se podría tirar una de las diversas excepciones uncatcheable incluyendo desbordamiento de pila o fuera de la memoria. Estas son las excepciones más difíciles de rastrear.

¿Qué aspecto tiene el consumo de memoria mientras se está ejecutando este subproceso? ¿Puedes usar un generador de perfiles de memoria para ver si está fuera de control? ¿Puedes agregar algo de registro en los bucles internos? Si tiene un método recursivo, agregue un contador y genere una excepción si repite una cantidad imposible de veces. ¿Está utilizando objetos grandes que podrían estar causando una gran fragmentación de montón de objetos (causa errores de memoria insuficiente incluso cuando no está realmente fuera).

5

Una posible forma de obtener más información: adjuntar un depurador y romper en la terminación del hilo. Dependiendo de cómo se termine el hilo, es posible que esto no funcione.

  1. Descargar Debugging Tools for Windows si no lo tiene
  2. Run windbg.exe, adjuntar a su proceso
  3. rotura en windbg, tipo sxe et para permitir rompiendo en salida de rosca
  4. Cuando se rompe el depurador , inspeccionar el estado del sistema, otros hilos, etc.
  5. Para obtener el pila administrada, sos.dll carga (.loadby sos mscorsvr, .loadby sos mscorwks o .loadby sos clr debería funcionar), a continuación, ejecutar !clrstack (ver !help para otros comandos sos)

Si sale mucho ruido de otros subprocesos que salen, script windbg para continuar después de romper si no es el identificador de subproceso que te importa.

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

+0

Si alguien está llamando a Thread.Abort() en su hilo, entonces puede tratar de atrapar la excepción especial ThreadAbortException, para saberlo. Esto no te dirá quién, pero te dirá cuándo. – Justin

1

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

2

Cuando se llama a RunWorker(), se puede añadir una referencia a su hilo a una lista. Una vez que haya detectado que su hilo ha muerto, puede inspeccionar el estado del hilo, quizás revele cómo murió. O, tal vez no ha muerto, solo 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); 
} 
} 
1

AsyncTasks utilizar para lograr su trabajo de larga ejecución en asp.net

Cuestiones relacionadas