Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Visual Studio bietet mehrere Tools und Benutzeroberflächenelemente, mit denen Sie Multithread-Anwendungen debuggen können. In diesem Tutorial wird gezeigt, wie Threadmarkierungen, das Fenster "Parallele Stapel", das Fenster "Parallele Überwachung", bedingte Haltepunkte und Filter-Haltepunkte verwendet werden. Wenn Sie dieses Lernprogramm abschließen, machen Sie sich mit den Visual Studio-Funktionen zum Debuggen von Multithread-Anwendungen vertraut.
Diese beiden Artikel enthalten zusätzliche Informationen zur Verwendung anderer Multithread-Debuggingtools:
Informationen zur Verwendung der Symbolleiste "Debug-Position" und des Fensters "Threads" finden Sie unter "Anleitung: Debuggen einer mehrteiligen Anwendung".
Ein Beispiel, das Task (verwalteter Code) und die Parallelitäts-Laufzeit (C++) verwendet, finden Sie unter Walkthrough: Debug a parallel application. Allgemeine Debugtipps, die für die meisten Multithread-Anwendungstypen gelten, finden Sie in diesem Artikel und in diesem Artikel.
Der erste Schritt besteht darin, ein Multithread-Anwendungsprojekt zu erstellen.
Erstellen eines Multithreadanwendungs-Projekts
Öffnen Sie Visual Studio, und erstellen Sie ein neues Projekt.
Wenn das Startfenster nicht geöffnet ist, wählen Sie Datei>Startfensteraus.
Wählen Sie im Startfenster Neues Projekt erstellen aus.
Geben Sie im Fenster Neues Projekt erstellen im Suchfeld Konsole ein. Wählen Sie als Nächstes C#, C++ oder Visual Basic aus der Liste "Sprache" aus, und wählen Sie dann Windows aus der Liste "Plattform" aus.
Nachdem Sie die Sprach- und Plattformfilter angewendet haben, wählen Sie die Konsolen-App-Vorlage für .NET oder C++ und dann "Weiter" aus.
Hinweis
Wenn die richtige Vorlage nicht angezeigt wird, wechseln Sie zu Tools>»Tools und Features abrufen«, wodurch das Visual Studio-Installationsprogramm geöffnet wird. Wählen Sie die .NET-Desktopentwicklung oder Desktopentwicklung mit C++ -Workload aus, und wählen Sie dann "Ändern" aus.
Geben Sie im Fenster "Neues Projekt konfigurieren" MyThreadWalkthroughApp in das Feld "Projektname" ein. Wählen Sie dann " Weiter" oder " Erstellen" aus, je nachdem, welche Option verfügbar ist.
Wählen Sie für ein .NET Core- oder .NET 5+-Projekt entweder das empfohlene Zielframework oder .NET 8 und dann "Erstellen" aus.
Ein neues Konsolenprojekt wird angezeigt. Nachdem das Projekt erstellt wurde, wird eine Quelldatei angezeigt. Je nach ausgewählter Sprache wird die Quelldatei möglicherweise Program.cs, MyThreadWalkthroughApp.cpp oder Module1.vb genannt.
Löschen Sie den Code, der in der Quelldatei angezeigt wird, und ersetzen Sie ihn durch den folgenden aktualisierten Code. Wählen Sie den entsprechenden Codeausschnitt für Ihre Codekonfiguration aus.
using System; using System.Threading; public class ServerClass { static int count = 0; // The method that will be called when the thread is started. public void InstanceMethod() { Console.WriteLine( "ServerClass.InstanceMethod is running on another thread."); int data = count++; // Pause for a moment to provide a delay to make // threads more apparent. Thread.Sleep(3000); Console.WriteLine( "The instance method called by the worker thread has ended. " + data); } } public class Simple { public static void Main() { for (int i = 0; i < 10; i++) { CreateThreads(); } } public static void CreateThreads() { ServerClass serverObject = new ServerClass(); Thread InstanceCaller = new Thread(new ThreadStart(serverObject.InstanceMethod)); // Start the thread. InstanceCaller.Start(); Console.WriteLine("The Main() thread calls this after " + "starting the new InstanceCaller thread."); } }
Wählen Sie im Menü Datei den Befehl Alle speichern aus.
(Nur Visual Basic) Klicken Sie im Projektmappen-Explorer (rechten Bereich) mit der rechten Maustaste auf den Projektknoten, und wählen Sie "Eigenschaften" aus. Ändern Sie auf der Registerkarte "Anwendung " das Startobjekt in "Einfach".
Fehlersuche in der Multithread-Anwendung durchführen
Suchen Sie im Quellcode-Editor nach dem folgenden Codeausschnitt:
Klicken Sie mit der linken Maustaste auf den linken Bundsteg der Anweisung
Thread.Sleep
oderstd::this_thread::sleep_for
(für C++), um einen neuen Breakpoint einzufügen.In diesem Bundsteg wird durch einen roten Kreis angezeigt, dass an dieser Stelle jetzt ein Haltepunkt festgelegt ist.
Wählen Sie im Menü " Debuggen " die Option " Debuggen starten " (F5) aus.
Visual Studio erstellt die Projektmappe, die Anwendung wird mit dem angefügten Debugger ausgeführt, und die Anwendung wird am Haltepunkt angehalten.
Suchen Sie im Quellcode-Editor die Zeile, die den Haltepunkt enthält.
Ermitteln des Threadmarkers
Wählen Sie in der Debugsymbolleiste die Schaltfläche "Threads im Quelltext anzeigen"
aus.
Drücken Sie F11 zweimal, um den Debugger zu wechseln.
Betrachten Sie den Bundsteg auf der linken Seite des Fensters. Beachten Sie in dieser Zeile ein Thread Marker Symbol
, das zwei verdrehten Fäden ähnelt. Die Threadmarkierung gibt an, dass an dieser Position ein Thread angehalten wird.
Ein Threadmarker kann teilweise durch einen Breakpoint verdeckt sein.
Zeigen Sie mit dem Mauszeiger auf den Threadmarker. Es wird eine Dateninfo angezeigt, die Ihnen den Namen und die Thread-ID-Nummer für jeden beendeten Thread angibt. In diesem Fall ist der Name wahrscheinlich
<noname>
.Wählen Sie den Thread-Marker aus, um die verfügbaren Optionen im Kurzmenü zu sehen.
Thread-Orte anzeigen
Im Fenster "Parallele Stapel" können Sie zwischen einer Threads-Ansicht und (für die aufgabenbasierte Programmierung) Aufgabenansicht wechseln, und Sie können Aufrufstapelinformationen für jeden Thread anzeigen. In dieser App können wir die Threads-Ansicht verwenden.
Öffnen Sie das Fenster "Parallele Stapel", indem Sie"Windows>Parallel-Stapel>" auswählen. Sie sollten etwas Ähnliches wie das Folgende sehen. Die genauen Informationen können je nach aktueller Position jedes Threads, Ihrer Hardware und Ihrer Programmiersprache variieren.
In diesem Beispiel sehen wir diese Informationen von links nach rechts für verwalteten Code:
- Der aktuelle Thread (gelber Pfeil) hat
ServerClass.InstanceMethod
betreten. Sie können die Thread-ID und das Stackfeld eines Threads anzeigen, indem Sie mit der Maus darüber fahrenServerClass.InstanceMethod
. - Thread 31724 wartet auf ein Schloss, das von Thread 20272 gehalten wird.
- Der Hauptthread (links) wurde auf [Externer Code] beendet, den Sie im Detail anzeigen können, wenn Sie "Externer Code anzeigen" auswählen.
In diesem Beispiel sehen wir diese Informationen von links nach rechts für verwalteten Code:
- Der Hauptthread (links) wurde bei
Thread.Start
angehalten, wobei der Stopppunkt durch das Threadmarkierungssymbolidentifiziert wird.
- Zwei Threads sind in
ServerClass.InstanceMethod
eingetreten, von denen einer der aktuelle Thread ist (gelber Pfeil), während der andere Thread inThread.Sleep
angehalten wurde. - Ein neuer Thread (auf der rechten Seite) wird ebenfalls gestartet, aber bei
ThreadHelper.ThreadStart
angehalten.
- Der aktuelle Thread (gelber Pfeil) hat
Um die Threads in einer Listenansicht anzuzeigen, wählen Sie">> aus.
In dieser Ansicht können Sie leicht erkennen, dass Thread 20272 der Hauptthread ist und sich derzeit im externen Code befindet, insbesondere System.Console.dll.
Hinweis
Weitere Informationen zur Verwendung des Threads-Fensters finden Sie unter Walkthrough: Debug a Multithreaded Application.
Klicken Sie mit der rechten Maustaste auf Einträge im Fenster "Parallele Stapel " oder " Threads ", um die verfügbaren Optionen im Kontextmenü anzuzeigen.
Sie können verschiedene Aktionen aus diesen Rechtsklick-Menüs ausführen. In diesem Lernprogramm erfahren Sie mehr über diese Details im Fenster " Parallele Überwachung " (nächste Abschnitte).
Eine Variable überwachen
Öffnen Sie das Fenster Parallelüberwachung, indem Sie Debug>Windows>Parallelüberwachung>Parallelüberwachung 1 auswählen.
Markieren Sie die Zelle, in der der
<Add Watch>
Text (oder die leere Kopfzeilenzelle in der vierten Spalte) angezeigt wird, und geben Sie eindata
.Die Werte für die Datenvariable für jeden Thread werden im Fenster angezeigt.
Markieren Sie die Zelle, in der der
<Add Watch>
Text (oder die leere Kopfzeilenzelle in der fünften Spalte) angezeigt wird, und geben Sie eincount
.Die Werte für die
count
Variable für jeden Thread werden im Fenster angezeigt. Wenn diese informationen noch nicht angezeigt werden, versuchen Sie, F11 ein paar Mal zu drücken, um die Ausführung der Threads im Debugger voranzutreiben.Klicken Sie mit der rechten Maustaste auf eine der Zeilen im Fenster, um die verfügbaren Optionen anzuzeigen.
Kennzeichnen von Threads und Aufheben der Kennzeichnung
Sie können Threads kennzeichnen, um wichtige Threads nachzuverfolgen und die anderen Threads zu ignorieren.
Halten Sie im Fenster „Parallele Überwachung“ die Umschalttaste gedrückt, und wählen Sie mehrere Zeilen aus.
Klicken Sie mit der rechten Maustaste, und wählen Sie Kennzeichnen aus.
Alle ausgewählten Threads werden gekennzeichnet. Jetzt können Sie filtern, um nur gekennzeichnete Threads anzuzeigen.
Wählen Sie im Fenster Parallele Überwachung die Schaltfläche Nur gekennzeichnete Threads anzeigen aus
.
Nur die gekennzeichneten Threads werden in der Liste angezeigt.
Tipp
Nachdem Sie einige Threads gekennzeichnet haben, können Sie im Code-Editor mit der rechten Maustaste auf eine Codezeile klicken und " Gekennzeichnete Threads zum Cursor ausführen" auswählen. Stellen Sie sicher, dass Sie Code auswählen, den alle gekennzeichneten Threads erreichen. Visual Studio hält Threads in der ausgewählten Codezeile an und erleichtert die Steuerung der Ausführungsreihenfolge durch Fixieren und Auftauen von Threads.
Wählen Sie erneut die Schaltfläche " Nur gekennzeichnete Threads anzeigen " aus, um zurück zum Modus "Alle Threads anzeigen " zu wechseln.
Um Threads aufzuheben, klicken Sie im Fenster "Parallele Überwachung " mit der rechten Maustaste auf einen oder mehrere gekennzeichnete Threads, und wählen Sie "Unflag" aus.
Einfrieren und Reaktivieren der Threadausführung
Tipp
Sie können Threads einfrieren und reaktivieren (anhalten und fortsetzen), um die Reihenfolge zu steuern, in der die Threads Aufgaben ausführen. Dies kann Ihnen helfen, Parallelitätsprobleme zu beheben, z. B. Deadlocks und Racebedingungen.
Klicken Sie im Fenster Parallele Überwachung, während alle Zeilen ausgewählt sind, mit der rechten Maustaste, und wählen Sie Einfrieren aus.
In der zweiten Spalte wird für jede Zeile ein Pausensymbol angezeigt. Das Pausensymbol gibt an, dass der Thread eingefroren ist.
Deaktivieren Sie alle anderen Zeilen, indem Sie nur eine Zeile auswählen.
Klicken Sie mit der rechten Maustaste auf eine Zeile, und wählen Sie "Thaw" aus.
Das Pausensymbol ist in dieser Zeile verschwunden, was darauf hinweist, dass der Thread nicht mehr eingefroren ist.
Wechseln Sie zum Code-Editor, und drücken Sie F11. Es wird nur der nicht eingefrorene Thread ausgeführt.
Die App möchte auch einige neue Threads instanziieren. Alle neuen Threads sind nicht gekennzeichnet und nicht eingefroren.
Folgen eines einzelnen Threads mit bedingten Haltepunkten
Es kann hilfreich sein, der Ausführung eines einzelnen Threads im Debugger zu folgen. Eine Möglichkeit dazu ist das Einfrieren von Threads, an denen Sie nicht interessiert sind. In einigen Szenarien müssen Sie möglicherweise einem einzelnen Thread folgen, ohne andere Threads einzufrieren, z. B. um einen bestimmten Fehler zu reproduzieren. Wenn Sie einem Thread folgen möchten, ohne andere Threads einzufrieren, müssen Sie das Unterbrechen von Code vermeiden, außer in dem Thread, an dem Sie interessiert sind. Sie können diese Aufgabe ausführen, indem Sie einen bedingten Haltepunkt festlegen.
Sie können Haltepunkte unter verschiedenen Bedingungen festlegen, z. B. den Threadnamen oder die Thread-ID. Es kann hilfreich sein, die Bedingung für die Daten festzulegen, von denen Sie wissen, dass sie einzigartig für jeden Thread sind. Dies ist ein gängiger Debugansatz, bei dem Sie mehr an einem bestimmten Datenwert als an einem bestimmten Thread interessiert sind.
Klicken Sie mit der rechten Maustaste auf den zuvor erstellten Haltepunkt, und wählen Sie "Bedingungen" aus.
Geben Sie im Fenster Haltepunkteinstellungen für den bedingten Ausdruck
data == 5
ein.Tipp
Wenn Sie mehr an einem bestimmten Thread interessiert sind, verwenden Sie einen Threadnamen oder eine Thread-ID für die Bedingung. Um dies im Fenster Haltepunkteinstellungen zu tun, wählen Sie Filter anstelle von bedingter Ausdruck aus und folgen Sie den Filtertipps. Möglicherweise möchten Sie Ihre Threads im App-Code benennen, da threads-IDs beim Neustart des Debuggers geändert werden.
Schließen Sie das Fenster " Haltepunkteinstellungen" .
Wählen Sie die Schaltfläche
aus, um Ihre Debugsitzung neu zu starten.
Sie unterteilen den Code im Thread, in dem der Wert der Datenvariable 5 ist. Suchen Sie im Fenster "Parallele Überwachung " nach dem gelben Pfeil, der den aktuellen Debuggerkontext angibt.
Jetzt können Sie Code überspringen (F10) und in Code einsteigen (F11) und der Ausführung des einzelnen Threads folgen.
Solange die Haltepunktbedingung für den Thread eindeutig ist und der Debugger keine anderen Haltepunkte in anderen Threads erreicht (Möglicherweise müssen Sie sie deaktivieren), können Sie Code durchlaufen und in Code wechseln, ohne zu anderen Threads zu wechseln.
Hinweis
Wenn Sie den Debugger voranbringen, werden alle Threads ausgeführt. Der Debugger unterbricht jedoch keinen Code in anderen Threads, es sei denn, einer der anderen Threads erreicht einen Haltepunkt.