25

Eine Sache, die mich ärgert, wenn ich Programme in Visual Studio (2005 in meinem Fall) zu debuggen ist, wenn ich "Schritt über" (durch Drücken F10) ausführen In der nächsten Zeile des Codes erreiche ich oft diese spezielle Codezeile in einem völlig anderen Thread als dem, den ich mir angesehen habe. Dies bedeutet, dass der gesamte Kontext dessen, was ich tat, verloren ging."Schritt über" beim Debuggen von Multithread-Programmen in Visual Studio

Wie kann ich das umgehen?

Wenn dies in späteren Versionen von Visual Studio möglich ist, möchte ich auch davon erfahren.

einen Haltepunkt auf der nächsten Zeile Code einstellen, die für diesen Thread nur zu brechen, um eine bedingte hat, ist nicht die Antwort, die ich suche, da es viel zu viel Arbeit ist für mich nützlich zu sein :)

Antwort

37

Ich denke, es gibt nur eine Antwort auf Ihre Frage, die Sie als "viel zu viel Arbeit" abgetan haben. Ich glaube jedoch, dass Sie das falsch machen. Lassen Sie mich Schritte zum Hinzufügen eines bedingten Haltepunkts auf Thread-ID vorstellen, die extrem einfach sind, aber nicht offensichtlich, bis Sie sie kennen.

  1. den Debugger an einem Punkt stoppen, wo Sie in den richtigen Thread sind Sie mit dem Debuggen in den Vorgang fortsetzen möchten (die ich schätze, würde, ist in der Regel der erste Thread, der bekommt dort). Geben Sie $TID in das Überwachungsfenster ein.

  2. einen Haltepunkt mit der Bedingung $TID == <Wert von $ TID von Watch Window>, hinzufügen
    Beispiel: $TID == 0x000016a0

  3. Execution Weiter.

$TID eine magische Variable für Microsoft-Compiler ist (da zumindest von Visual Studio     2003), die den Wert der aktuellen Thread-ID hat. Es macht es viel einfacher als das Betrachten (FS + 0x18) [0x24]. = D

Das heißt, Sie können das gleiche Verhalten wie die One-Shot Breakpoints des Debuggers mit einigen einfachen Makros erhalten. Wenn Sie einen Schritt ausführen, setzt der Debugger hinter den Kulissen einen Haltepunkt, führt diesen Haltepunkt aus und entfernt ihn dann. Der Schlüssel zu einer konsistenten Benutzerschnittstelle ist das Entfernen dieser Haltepunkte, wenn ANY Haltepunkt erreicht wird.

Die folgenden zwei Makros bieten Step Over und Run To für den aktuellen Thread Cursor. Dies geschieht auf die gleiche Weise wie der Debugger, wobei die Breakpoints nach der Ausführung entfernt werden, unabhängig davon, welcher Breakpoint getroffen wird.

Sie möchten eine Tastenkombination zuweisen, um sie auszuführen.

HINWEIS: Eine Warnung - Der Step Over nur Makro funktioniert einwandfrei, wenn der Cursor Sie auf der Linie wollen, ist über Schritt. Dies liegt daran, dass die aktuelle Position durch die Cursorposition bestimmt wird und einfach eine Zeile zur Zeilennummer hinzugefügt wird. Möglicherweise können Sie die Standortberechnung durch Informationen zum aktuellen Ausführungspunkt ersetzen, obwohl ich diese Informationen nicht von der Macro IDE finden konnte.

Hier sind sie und viel Glück Bugjagd !!

Um diese Makros in Visual Studio zu verwenden:
1. Öffnen Sie die Makro-IDE (aus dem Menü wählen: Tools-> Makros-> Makro IDE ...)
2. Hinzufügen eine neue Code-Datei (aus dem Menü: wählen: Ausbau-> neues Element hinzufügen ..., wählt -Code Datei und klicken Sie hinzufügen)
3.es Einfügen in diesem Code.
4. Speichern Sie die Datei.

Um Tastenkombinationen hinzufügen für diese Makros in Visual Studio ausgeführt wird:
1. Öffnen Sie Optionen (aus dem Menü wählen: Tools-> Optionen)
2. bis erweitern Umfeld-> Tastatur
3. In Befehle anzeigen, die Folgendes enthalten:, Typ Makros., um alle Ihre Makros zu sehen.
4. ein Makro auswählen, dann klicken Sie in Drücken von Tastenkombinationen:
5. Geben Sie die Combo Sie (Backspace löscht getippt Combos)
6. Klick Assign setzen Ihre Verknüpfung verwenden, ausgeführt werden soll das ausgewählte Makro.

Imports System 
Imports EnvDTE 
Imports EnvDTE80 
Imports System.Diagnostics 

Public Module DebugHelperFunctions 

    Sub RunToCursorInMyThread() 
     Dim textSelection As EnvDTE.TextSelection 
     Dim myThread As EnvDTE.Thread 
     Dim bp As EnvDTE.Breakpoint 
     Dim bps As EnvDTE.Breakpoints 

     ' For Breakpoints.Add() 
     Dim FileName As String 
     Dim LineNumber As Integer 
     Dim ThreadID As String 

     ' Get local references for ease of use 
     myThread = DTE.Debugger.CurrentThread 
     textSelection = DTE.ActiveDocument.Selection 

     LineNumber = textSelection.ActivePoint.Line 
     FileName = textSelection.DTE.ActiveDocument.FullName 
     ThreadID = myThread.ID 

     ' Add a "One-Shot" Breakpoint in current file on current line for current thread 
     bps = DTE.Debugger.Breakpoints.Add("", FileName, LineNumber, 1, "$TID == " & ThreadID) 

     ' Run to the next stop 
     DTE.Debugger.Go(True) 

     ' Remove our "One-Shot" Breakpoint 
     For Each bp In bps 
      bp.Delete() 
     Next 
    End Sub 

    Sub StepOverInMyThread() 
     Dim textSelection As EnvDTE.TextSelection 
     Dim myThread As EnvDTE.Thread 
     Dim bp As EnvDTE.Breakpoint 
     Dim bps As EnvDTE.Breakpoints 

     ' For Breakpoints.Add() 
     Dim FileName As String 
     Dim LineNumber As Integer 
     Dim ThreadID As String 

     ' Get local references for ease of use 
     myThread = DTE.Debugger.CurrentThread 
     textSelection = DTE.ActiveDocument.Selection 

     LineNumber = textSelection.ActivePoint.Line 
     FileName = textSelection.DTE.ActiveDocument.FullName 
     ThreadID = myThread.ID 
     LineNumber = LineNumber + 1 

     ' Add a "One-Shot" Breakpoint in current file on current line for current thread 
     bps = DTE.Debugger.Breakpoints.Add("", FileName, LineNumber, 1, "$TID == " & ThreadID) 

     ' Run to the next stop 
     DTE.Debugger.Go(True) 

     ' Remove our "One-Shot" Breakpoint 
     For Each bp In bps 
      bp.Delete() 
     Next 
    End Sub 


End Module 

Haftungsausschluss: Ich schrieb dieses Makros in Visual Studio 2005. Sie können sie wahrscheinlich gut in Visual Studio 2008 verwenden. Sie müssen möglicherweise für Visual Studio 2003 und vorher geändert werden.

+0

Funktioniert das für jeden? Ich konnte es nicht funktionieren lassen. –

+0

Es funktioniert für mich. = D Was war dein Fehler? – Aaron

+0

@Aaron: Ich benutze VS 2008, wenn ich $ TID im Watch-Fenster gebe ich bekomme den Fehler "Der Name existiert nicht im aktuellen Kontext" – akif

21

Sie können einen anderen Thread einfrieren oder zu einem anderen Thread wechseln, indem Sie das Thread-Debug-Fenster verwenden (Ctrl + Alt + H).

+0

Danke. Dies ist der besten Lösung, die ich bisher gesehen habe, am nächsten! – Laserallan

+4

Das mache ich auch, die Frage ist ... warum ändert ein einzelner Schritt den ausführenden Thread? –

6

Die einfache Möglichkeit, einen bestimmten Thread zu debuggen, besteht darin, alle anderen Threads im Thread-Fenster einzufrieren.

+3

Gibt es keine Möglichkeit, VS nur nicht zwischen Threads wechseln zu lassen? In welcher Situation macht es sogar Sinn, dass ein Debugger beim Überschreiten einer Leitung auf einen anderen Thread umschaltet und erwartet, einfach zum nächsten zu gelangen? – stu

+0

Hat jemand dafür ein Makro?Es wäre schön für ein Plugin oder ein Makro, wenn man alle anderen Threads überstarrt, alle Zeilen abtastet und dann alle anderen Threads freigibt. Das ist effektiv, was ich tun möchte, es sollte eine Möglichkeit geben, das zu automatisieren. – stu

+0

Natürlich sollte es im Visual Studio überhaupt erst richtig funktionieren. – stu

2

[Strg + D, T] oder [Strg + Alt + H] - Öffnet das Thema Fenster (zur Überwachung, einfrieren und den Namen Fäden)

Der Thread-Fenster können Sie auswählen, ob Sie anzeigen möchten die Position der anderen Threads im Visual Studio. Das ist eine gute Erinnerung für mich, dass der aktuelle Thread, den ich debugge, nicht der einzige im Spiel ist. Wenn Sie über die Fadenmarke fahren, erhalten Sie den Namen und die ID der Fäden.

Weitere Tipps finden Sie unter: http://devpinoy.org/blogs/jakelite/archive/2009/01/10/5-tips-on-debugging-multi-threaded-code-in-visual-studio-net.aspx

2

Offenbar Visual Studio 2010 nur zu anderen Threads schaltet, wenn Sie F10 drücken, wenn der Debugger vor oder wenn ein Haltepunkt in diesem Thread zu brechen hatte gesetzt, die getroffen wird, in diesem Thread.

habe ich den folgenden Code, um das Verhalten zu testen:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var t = new Thread(new ThreadStart(Work)); 
     t.Start(); 

     for (int i = 0; i < 20; i++) 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("............"); 
     } 

     t.Join(); 
    } 

    static void Work() 
    { 
     for (int i = 0; i < 20; i++) 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("ZZzzzzzzzzzzzzzz"); 
     } 
    } 
} 

Wenn Sie das Programm nur stept oder einen Haltepunkt in der Main() Methode hinzufügen, F10 nur ein paar Schritte durch den Code aus dem Haupt-Thread schlagen .

Wenn Sie einen Haltepunkt in der Work()-Methode hinzufügen, durchläuft der Debugger beide Threads.

Dieses Verhalten von Visual Studio macht Sinn, aber es scheint wie eine nicht dokumentierte Funktion zu mir ...

1

Vor kurzem hatte ich das gleiche Problem nur einen bestimmten Thread von debuggen. Während ich die obige Antwort nicht als sehr umfassend und wertvoll (und ich wünschte, ich hätte es vor 2 Tagen gefunden), habe ich Folgendes implementiert, um "alltägliche" Fehlersuche zu unterstützen.

Diese Idee ist nur eine einfache Problemumgehung, wenn mehrere Instanzen der gleichen Klasse in mehreren Threads ausgeführt werden - was unsere Anwendung zu jeder Zeit tut.

Wir initialisieren alle Klasseninstanzen mit einer eindeutigen ID oder einem eindeutigen Namen, damit wir wissen, wie oder warum die Instanz erstellt wurde. Dann, wenn wir eine bestimmte Instanz debuggen müssen (dh Thread) - und nicht andere Threads einfrieren, fügen wir folgendes:

if (instance.ID == myID) 
{ 
    // Assert BreakPoint 
} 

In unserem Fall schaffen wir feste IDs, so kennen wir die ID wir wollen Fehlerbehebung, wenn ein Problem auftritt.

Verwandte Themen