¿Cómo depurar un solo hilo en Visual Studio?

254

Tengo una solución con algunos proyectos. Hay varios puntos de quiebre en diferentes proyectos. Quiero rastrear el primer hilo alcanzado uno de estos puntos de quiebre y continuar rastreando ese hilo único a pesar de que otros hilos entren en los mismos bloques de código.

Sé que esto es posible mediante la definición de una condición en el punto de interrupción, es decir, nombre de subproceso = ... o Id de subproceso = ... pero mi caso es una aplicación ASP.NET cargada y tan pronto como me conecto a w3wp.exemuchos los hilos alcanzarán los puntos de quiebre. Necesito algo como a ThreadLocal<break-point>.

¿Es posible? ¿Si es así, cómo?

Xaqron
fuente
77
@Paolo: esta aplicación web funciona como el corazón de una gran granja web y la situación con errores es imposible de imitar en escenarios de prueba.
Xaqron
Para VS 2019, tal vez debería intentar esto: stackoverflow.com/a/61868591/8579563
Gozo

Respuestas:

151

Congelar / descongelar hilos es una forma incorrecta porque otros hilos no ejecutan ningún código.

La forma más correcta y útil es:

  1. Presione Ctrl + A en la ventana de puntos de interrupción (seleccione todos los puntos de interrupción).
  2. Haga clic derecho y seleccione "Filtro ...".
  3. Ingrese "ThreadId = (id. De hilo actual)".

En Visual Studio 2015 y versiones posteriores, el proceso es similar:

  1. Presione Ctrl + A en la ventana de puntos de interrupción (seleccione todos los puntos de interrupción).
  2. Haga clic derecho y seleccione "Configuración ...".
  3. Marque "Condiciones" y seleccione "Filtro" en el menú desplegable
  4. Ingrese "ThreadId = (id. De hilo actual)".

Por lo tanto, todos los subprocesos se ejecutan, pero el depurador solo llega al subproceso actual.

hzdbyte
fuente
51
¿Esto evita que el comando de depurador "Paso" ingrese otros hilos? Ese fue un gran problema que tuve. Estoy pasando por mi hilo y, de repente, estoy en una porción de código completamente no relacionada. Ya no desarrollo en Visual Studio, así que no puedo probar.
Matt Faus
8
Al hacer clic con el botón derecho en la ventana de puntos de interrupción no hay un comando de "filtro" ... ¿y cómo se encuentra el Id. De hilo actual de todos modos? - ¿Vas a la ventana inmediata y escribes System.Threading.Thread.CurrentThread.ManagedThreadIdo algo así?
BrainSlugs83
55
En mi VS (2015, Community Edition) no es posible modificar la configuración de múltiples puntos de interrupción a la vez. Por lo tanto, el filtro se puede configurar solo uno por uno.
robert4
55
He tenido este problema para siempre, y podría jurar que en mi último trabajo encontré una configuración que hacía que el estudio visual funcionara como un eclipse en el que te apegarías al hilo con el que estabas trabajando, pero no puedo encontrarlo ni ninguna referencia lo. Estoy empezando a preguntarme si lo soñé.
stu
77
-1 porque esto solo permite puntos de interrupción, pero no para depurar realmente: paso a paso no funciona de esta manera para depurar un solo hilo.
Serge Rogatch
338

Esto es lo que hice:

  1. Establezca un punto de interrupción condicional que sabía que solo golpearía el hilo que estaba buscando.

  2. Una vez que llegue el punto de interrupción y esté en el hilo que desea, en la ventana de hilos de Visual Studio (durante la depuración, Depuración -> Windows -> Hilos), Ctrl+ A(para seleccionar todos los hilos) y luego Ctrlhaga clic en el hilo en el que se encuentra actualmente . Debería tener todos los hilos excepto el que desea depurar seleccionado.

  3. Haga clic derecho y elija "Congelar".

Ahora, Visual Studio solo atravesará el hilo descongelado. Parece que es mucho más lento al hacer esto, presumiblemente porque tiene que recorrer todos los hilos congelados, pero aportó algo de cordura a mi depuración de subprocesos múltiples.

Matt Faus
fuente
1
Esto no funciona para mí en un contexto donde tengo alrededor de 8 tareas ejecutándose en diferentes hilos. Congelo todos los otros hilos y "paso", pero el IDE se congela por un tiempo, luego salta a otro hilo de todos modos.
Meta-Knight
3
@Diego: ya no estoy trabajando en el proyecto, pero si va a congelar todos los hilos excepto uno, cambiará el escenario que causó el error, ya que los hilos eran complementarios en la situación de error. Aunque esta es una solución elegante, parece que esta característica debería integrarse en VS.
Xaqron
3
@ Meta-Knight Debes congelar todos los hilos excepto el Tema Principal. Si lo haces así, IDE no se congelará
Alex Zhukovskiy
15

Acabo de lanzar una extensión de Visual Studio 2010+ que hace exactamente lo que estás buscando. Y es gratis :).

Presentación

Esta extensión de Visual Studio agrega dos accesos directos y botones de barra de herramientas para permitir a los desarrolladores centrarse fácilmente en subprocesos individuales mientras depuran aplicaciones de subprocesos múltiples.

Reduce drásticamente la necesidad de acceder manualmente a la ventana Subprocesos para congelar / descongelar todos los subprocesos, excepto el que debe seguirse, y por lo tanto ayuda a mejorar la productividad.

Caracteristicas

Restrinja la ejecución posterior solo al hilo actual. Congelará todos los otros hilos. Atajo: CTRL + T + T o botón Copo de nieve. Cambie al siguiente subproceso individual (según la ID). Cambiará el hilo actual y congelará todos los otros hilos. Atajo: CTRL + T + J o el botón Siguiente.

Compruébelo aquí en la Galería , en la página oficial o en el repositorio de Github .

Erwin Mayer
fuente
¿Qué versión de VS estás usando?
Erwin Mayer
Instalé la extensión, pero no logré que funcionara (para mi proyecto actual, uso VS2010). [Por cierto, lo que pensé que era un problema con los hilos que se activan solo sucede cuando se crean hilos, probablemente es un comportamiento estándar, así que eliminé mi comentario anterior].
wip
3
Voy a revisar esto. Puede ser la única persona en el planeta que haya intentado resolver una de las fallas de depuración más grandes de Microsoft.
stu
Por desgracia, no se instalará en vs2012. ¿Tiene una versión más nueva o quiere compartir el código fuente para que yo pueda construirlo yo mismo?
stu
@stu El código fuente está en Codeplex aquí: singlethread.codeplex.com , debería funcionar en VS 2012 y VS 2013, pero no lo he actualizado (nadie lo ha solicitado y yo tampoco he tenido la necesidad). Si puede hacer que funcione fácilmente con VS 2012+ y hacer una confirmación en Codeplex, entonces también puedo incluirlo en la Galería.
Erwin Mayer
13

Si se generan múltiples hilos como para una aplicación web, las respuestas de @MattFaus no funcionarán. lo que hice en su lugar es lo siguiente

  • Configure un punto de interrupción para interrumpir el hilo en la función que quiero.
  • Una vez que el subproceso llega al punto de interrupción y se detiene, elimino el punto de interrupción y continúo la depuración con F8, F10 y F11, para que los otros subprocesos puedan ejecutarse.
Mikaël Mayer
fuente
Después de leer todas las respuestas principales, esta solución me funcionó.
Swanand Pangam
9

Un enfoque ligeramente diferente que he usado:

  1. Crea un punto de interrupción normal y deja que te golpee
  2. Busque en su ventana de hilos la ID de hilo administrado que está depurando actualmente
  3. Haga clic derecho en su punto de interrupción en la ventana de puntos de interrupción y seleccione el filtro
  4. Ingrese ThreadId = xxx donde xxx es la ID del hilo de 2
  5. Ahora puede depurar sin detener otros hilos y sin que lleguen a su punto de interrupción

Esto supone que tiene tiempo para hacer lo anterior antes de que un segundo hilo llegue a su punto de interrupción. Si no, y otros hilos llegan a su punto de interrupción antes de que haya hecho lo anterior, puede hacer clic derecho en ellos en la ventana de hilos y elegir congelar.

Mate
fuente
3
+1. "Esto supone que tienes tiempo ... antes de que un segundo hilo llegue a tu punto de ruptura". Envuelvo un punto y coma en un candado y pongo un punto de interrupción en el punto y coma. Cuando se alcanza el punto de interrupción por primera vez, desactivo el punto de interrupción. No pueden entrar otros hilos debido al bloqueo. lock(m_someObject) { ; }
bluedog
Para guardar un Google, la ventana de subprocesos se encuentra en Depurar> Windows> Subprocesos.
Gabe
2

En VS 2019:

  1. Establecer un punto de interrupción en alguna parte.
  2. Presiona F5 (Continuar) hasta que aparezca tu hilo.
  3. Haga clic en el punto de interrupción para eliminarlo.
  4. Puede pasar el hilo con F10 o F11.
Gozo
fuente
¡Funciona también para VS2015!
prehistoricpenguin
1

Sugeriría agregar otra instancia de la aplicación en el servidor en vivo, ya sea en el mismo hardware o en una nueva máquina (agruparla) y luego depurar solo esa instancia. No agregaría un punto de interrupción en el código que los usuarios están activando. Si esa no es una opción, agregaría más rastreo.

Sin embargo, si esto es absolutamente necesario y necesita una estadística de solución, estoy seguro de que podría agregar un punto de interrupción que se rompa solo si la solicitud proviene de su dirección IP. Lo haría agregando un punto de interrupción condicional que inspeccione HttpContext.Request.UserHostAddress. Sin embargo, tenga en cuenta que esto ralentiza su aplicación considerablemente.

steinar
fuente
Eso es lo que he intentado. El problema es que esta instancia no funciona en el mismo dominio (que se ejecuta en IP u otro dominio) y esto lleva a muchos problemas de certificado (SSL, WCF, ...) y también bajo carga, ¡la situación de error nunca sucede!
Xaqron
Lo siento, no estoy seguro de cuál de estos has probado, ¿has probado el punto de corte condicional?
steinar
Sí, los nombré en función de su Id administrado para garantizar la unicidad. Entonces es difícil adivinar qué Id está asignado y establecer la condición en función de una suposición. A veces, la suposición está cerca y, a veces, lleva mucho tiempo atrapar el hilo.
Xaqron
1

Si no desea detener todos los demás subprocesos (tal vez está adjuntando el depurador de Visual Studio a una aplicación en ejecución que necesita responder a las solicitudes), puede usar una macro que cree y elimine puntos de interrupción automáticamente.

Esto se sugiere en una respuesta a la pregunta " Desbordamiento de pila " al depurar programas multiproceso en Visual Studio .

Sin embargo, el enlace solo explica cómo depurar línea por línea. Le sugiero que modifique la macro (si se siente cómodo con ella) para que modifique todos los puntos de interrupción (en un rango de línea dado, por ejemplo) para que se detenga solo en el hilo actual.

kamaradclimber
fuente
1

Creo que esto es ligeramente diferente en Visual Studio 2015. Han cambiado algunas cosas en los puntos de interrupción, pero así es cómo aplicar la respuesta aceptada de hzdbyte (arriba):

En el punto de interrupción en el margen de codificación, haga clic con el botón derecho> Condiciones> Cambiar de 'Expresión condicional' a 'Filtro'. Esto le permite filtrar por ThreadId.

Alternativamente, en el punto de interrupción en la ventana Puntos de interrupción, haga clic con el botón derecho> Configuración> marque el cuadro Condiciones y haga lo anterior.

Patelos
fuente
1

Establezca una Condición de punto de interrupción haciendo clic derecho en la barra lateral de la línea. Seleccione "Condición" e ingrese lo siguiente con el nombre de su hilo entre comillas:

System.Threading.Thread.CurrentThread.Name == "name_of_your_thread"

Alternativamente, puede hacer lo mismo obteniendo el "ID administrado" del hilo de la ventana "Hilos" y usar:

System.Threading.Thread.CurrentThread.ManagedThreadId == your_managed_thread_id

James Sheridan
fuente