Comment déboguer un seul thread dans Visual Studio?

254

J'ai une solution avec certains projets. Il existe plusieurs points d'arrêt dans différents projets. Je veux tracer le premier thread a atteint l'un de ces points d'arrêt et continuer à tracer ce thread unique malgré d'autres threads entrant dans les mêmes blocs de code.

Je sais que cela est possible en définissant une condition sur le point d'arrêt, c'est-à-dire le nom du thread = ... ou l'ID du thread = ... mais mon cas est une application ASP.NET chargée et dès que je l'attache à w3wp.exeplusieurs les threads atteindront les points d'arrêt. J'ai besoin de quelque chose comme un ThreadLocal<break-point>.

C'est possible? Si c'est le cas, comment?

Xaqron
la source
7
@Paolo: Cette application Web fonctionne comme le cœur d'une grande ferme Web et la situation de buggy est impossible à imiter dans les scénarios de test.
Xaqron
Pour VS 2019, vous devriez peut-être essayer ceci: stackoverflow.com/a/61868591/8579563
Gozo

Réponses:

151

Geler / Décongeler les threads est une manière incorrecte car les autres threads n'exécutent aucun code.

La manière la plus correcte et la plus utilisable consiste à:

  1. Appuyez sur Ctrl + A dans la fenêtre des points d'arrêt (sélectionnez tous les points d'arrêt).
  2. Faites un clic droit et sélectionnez "Filtre ...".
  3. Entrez "ThreadId = (id de thread actuel)".

Dans Visual Studio 2015 et versions ultérieures, le processus est similaire:

  1. Appuyez sur Ctrl + A dans la fenêtre des points d'arrêt (sélectionnez tous les points d'arrêt).
  2. Faites un clic droit et sélectionnez "Paramètres ...".
  3. Cochez "Conditions" et sélectionnez "Filtre" dans la liste déroulante
  4. Entrez "ThreadId = (id de thread actuel)".

Tous les threads sont donc exécutés, mais le débogueur ne frappe que le thread actuel.

hzdbyte
la source
51
Cela empêche-t-il la commande de débogage "Step" d'entrer d'autres threads? C'était un gros problème que j'avais. Je passe à travers mon fil et tout à coup, je suis dans une partie complètement indépendante du code. Je ne développe plus dans Visual Studio, donc je ne peux pas tester.
Matt Faus
8
Un clic droit dans la fenêtre des points d'arrêt n'a pas de commande "filtre" ... et comment trouvez-vous quand même l'identifiant du thread actuel? - Allez-vous à la fenêtre immédiate et en tapant System.Threading.Thread.CurrentThread.ManagedThreadIdou quelque chose?
BrainSlugs83
5
Dans mon VS (2015, Community Edition), il n'est pas possible de modifier les paramètres de plusieurs points d'arrêt à la fois. Ainsi, le filtre ne peut être réglé qu'un par un.
robert4
5
J'ai eu ce problème pour toujours, et je pourrais jurer lors de mon dernier travail que j'ai trouvé un paramètre qui faisait fonctionner Visual Studio comme Eclipse où vous vous en tiendriez au fil avec lequel vous travailliez, mais je ne le trouve pas ou aucune référence à elle. Je commence à me demander si j'en ai rêvé.
stu
7
-1 car cela n'autorise que les points d'arrêt, mais pas le débogage: les étapes / pas ne fonctionnent pas de cette façon pour le débogage d'un seul thread.
Serge Rogatch
338

Voici ce que j'ai fait:

  1. Définissez un point d'arrêt conditionnel qui, je le savais, ne toucherait que le thread que je recherchais.

  2. Une fois que le point d'arrêt atteint et que vous êtes dans le thread souhaité, dans la fenêtre Threads de Visual Studio (pendant le débogage, Débogage -> Windows -> Threads), Ctrl+ A(pour sélectionner tous les threads), puis Ctrl+ cliquez sur le thread sur lequel vous êtes actuellement . Vous devez avoir tous les threads à l'exception de celui que vous souhaitez déboguer sélectionné.

  3. Faites un clic droit et choisissez "Geler".

Maintenant, Visual Studio ne parcourra que le thread décongelé. Cela semble être beaucoup plus lent lors de cette opération, probablement parce qu'il doit parcourir tous les threads gelés, mais cela a apporté un peu de raison à mon débogage multithread.

Matt Faus
la source
1
Cela ne fonctionne pas pour moi dans un contexte où j'ai environ 8 tâches s'exécutant dans différents threads. Je fige tous les autres threads et "enjambe" mais l'IDE se fige pendant un certain temps, puis passe à un autre thread de toute façon.
Meta-Knight
3
@Diego: Je ne travaille plus sur le projet mais s'il va geler tous les threads sauf un, cela changera le scénario qui a causé le bug, car les threads étaient complémentaires en situation de buggy. Bien qu'il s'agisse d'une solution élégante, il semble que cette fonctionnalité devrait être intégrée dans VS.
Xaqron
3
@ Meta-Knight Vous devez geler tous les threads sauf le thread principal. Si vous voulez faire comme ça, l'IDE ne sera pas gelé
Alex Zhukovskiy
15

Je viens de publier une extension Visual Studio 2010+ qui fait exactement ce que vous recherchez. Et c'est gratuit :).

Présentation

Cette extension Visual Studio ajoute deux raccourcis et boutons de barre d'outils pour permettre aux développeurs de se concentrer facilement sur des threads uniques lors du débogage d'applications multi-thread.

Il réduit considérablement la nécessité d'accéder manuellement à la fenêtre Threads pour figer / décongeler tous les threads, sauf celui qui doit être suivi, et contribue donc à améliorer la productivité.

Caractéristiques

Restreindre l'exécution au thread actuel uniquement. Gèle tous les autres threads. Raccourci: CTRL + T + T ou bouton Flocon de neige. Basculez vers le thread unique suivant (basé sur l'ID). Modifie le thread actuel et gèle tous les autres threads. Raccourci: CTRL + T + J ou bouton Suivant.

Découvrez-le ici sur la Galerie , sur la page officielle ou le référentiel Github .

Erwin Mayer
la source
Quelle version de VS utilisez-vous?
Erwin Mayer
J'ai installé l'extension, mais je n'ai pas réussi à la faire fonctionner (pour mon projet actuel, j'utilise VS2010). [Au fait, ce que je pensais être un problème avec l'activation des threads ne se produit que lorsque les threads sont créés, c'est probablement un comportement standard, j'ai donc supprimé mon commentaire précédent].
essuyez
3
Je vais vérifier ça. Vous êtes peut-être la seule personne sur la planète à avoir tenté de résoudre l'un des plus gros échecs de débogage de Microsoft.
stu
hélas, il ne s'installera pas sur vs2012. Avez-vous une version plus récente ou allez-vous partager le code source afin que je puisse le construire moi-même?
stu
@stu Le code source est sur Codeplex ici: singlethread.codeplex.com il devrait fonctionner sur VS 2012 et VS 2013 mais je ne l'ai pas mis à jour (personne ne l'a demandé et je n'en ai pas eu besoin moi-même). Si vous pouvez le faire fonctionner facilement avec VS 2012+ et faire un commit sur Codeplex, je peux également le pousser sur la galerie.
Erwin Mayer
13

Si plusieurs threads sont générés comme pour une application Web, les réponses @MattFaus ne fonctionneront pas. ce que j'ai fait à la place est le suivant

  • Configurez un point d'arrêt pour interrompre le thread dans la fonction que je souhaite.
  • Une fois que le thread atteint le point d'arrêt et est en pause, je supprime le point d'arrêt et continue le débogage à l'aide de F8, F10 et F11, afin que les autres threads puissent s'exécuter.
Mikaël Mayer
la source
Après avoir lu tous les meilleurs anserws, cette solution de contournement a fonctionné pour moi.
Swanand Pangam
9

Une approche légèrement différente que j'ai utilisée:

  1. Créez un point d'arrêt normal et laissez-le toucher
  2. Recherchez dans votre fenêtre de threads l'ID de thread géré que vous déboguez actuellement
  3. Faites un clic droit sur votre point d'arrêt dans la fenêtre des points d'arrêt et filtre de sélection
  4. Entrez ThreadId = xxx où xxx est l'ID de thread de 2
  5. Vous pouvez maintenant déboguer sans arrêter les autres threads et sans qu'ils atteignent votre point d'arrêt

Cela suppose que vous avez le temps de faire ce qui précède avant qu'un deuxième thread atteigne votre point d'arrêt. Si ce n'est pas le cas et que d'autres threads atteignent votre point d'arrêt avant d'avoir fait ce qui précède, vous pouvez cliquer dessus avec le bouton droit de la souris dans la fenêtre des threads et choisir figer.

Mat
la source
3
+1. "Cela suppose que vous avez le temps ... avant qu'un deuxième thread n'atteigne votre point d'arrêt". J'enveloppe un point-virgule dans une serrure et mets un point d'arrêt sur le point-virgule. Lorsque le point d'arrêt est atteint la première fois, je désactive le point d'arrêt. Aucun autre filetage ne peut entrer à cause du verrou. lock(m_someObject) { ; }
bluedog
Pour vous sauver un Google, la fenêtre des discussions se trouve sous Debug> Windows> Threads.
Gabe
2

Dans VS 2019:

  1. Définissez un point d'arrêt quelque part.
  2. Appuyez sur F5 (continuer) jusqu'à ce que votre fil arrive.
  3. Cliquez sur le point d'arrêt pour le supprimer.
  4. Vous pouvez avancer le fil avec F10 ou F11.
Gozo
la source
Fonctionne aussi pour VS2015!
pingouin préhistorique
1

Je suggérerais d'ajouter une autre instance de l'application sur le serveur en direct, soit sur le même matériel ou sur une nouvelle machine (la mettre en cluster), puis de déboguer uniquement cette instance. Je n'ajouterais pas de point d'arrêt dans le code que les utilisateurs déclenchent. Si ce n'est pas une option, j'ajouterais plus de traçage.

Cependant, si cela est absolument nécessaire et que vous avez besoin d'une stat de solution, je suis sûr que vous pouvez ajouter un point d'arrêt qui ne s'arrête que si la demande provient de votre adresse IP. Pour ce faire, vous ajoutez un point d'arrêt conditionnel qui inspecte HttpContext.Request.UserHostAddress. Notez cependant que cela ralentit considérablement votre application.

steinar
la source
Voilà ce que j'ai essayé. Le problème est que cette instance ne fonctionne pas sur le même domaine (fonctionnant sur IP ou un autre domaine) et cela conduit à de nombreux problèmes de certificats (SSL, WCF, ...) et également à faible charge, la situation de buggy ne se produit jamais!
Xaqron
Désolé, je ne sais pas lequel de ceux que vous avez essayé, avez-vous essayé le point d'arrêt conditionnel?
steinar
Oui, je les ai nommés en fonction de leur identifiant géré pour garantir l'unicité. Ensuite, il est difficile de deviner quel ID est attribué et de définir la condition en fonction d'une supposition. Parfois, la supposition est proche et parfois il faut beaucoup de temps pour attraper le fil.
Xaqron
1

Si vous ne souhaitez pas arrêter tous les autres threads (peut-être que vous attachez le débogueur Visual Studio à une application en cours d'exécution qui doit répondre aux demandes), vous pouvez utiliser une macro qui crée et supprime automatiquement des points d'arrêt.

Cela est suggéré dans une réponse à la question de dépassement de pile "Étape" lors du débogage de programmes multithread dans Visual Studio .

Cependant, le lien explique uniquement comment déboguer ligne par ligne. Je vous suggère de modifier la macro (si vous êtes à l'aise avec elle) pour lui faire modifier tous les points d'arrêt (dans une plage de ligne donnée par exemple) pour ne s'arrêter que sur le thread actuel.

kamaradclimber
la source
1

Je pense que c'est légèrement différent dans Visual Studio 2015. Ils ont changé quelques choses dans les points d'arrêt, mais voici comment appliquer la réponse acceptée de hzdbyte (ci-dessus):

Sur le point d'arrêt dans la marge de codage, cliquez avec le bouton droit sur> Conditions> Passer de «Expression conditionnelle» à «Filtre». Cela vous permet ensuite de filtrer par ThreadId.

Sinon, sur le point d'arrêt dans la fenêtre Points d'arrêt, cliquez avec le bouton droit sur> Paramètres> cochez la case Conditions et procédez comme ci-dessus.

Patelos
la source
1

Définissez une condition de point d'arrêt en cliquant avec le bouton droit sur la barre latérale de la ligne. Sélectionnez "Condition" et entrez ce qui suit avec le nom de votre fil entre guillemets:

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

Alternativement, vous pouvez faire la même chose en récupérant l '"ID géré" du thread dans la fenêtre "Threads" et en utilisant:

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

James Sheridan
la source