Debuggen von Multithreadanwendungen in Visual Studio

Ein Thread ist eine Folge von Anweisungen, für die das Betriebssystem Prozessorzeit vergibt. Jeder Prozess, der im Betriebssystem ausgeführt wird, umfasst mindestens einen Thread. Prozesse, die über mehr als einen Thread verfügen, werden als Multithreadprozesse bezeichnet.

Auf Computern mit mehreren Prozessoren, Mehrkernprozessoren oder Hyperthreadingprozessen können mehrere gleichzeitige Threads ausgeführt werden. Die parallele Verarbeitung mit vielen Threads kann die Programmleistung erheblich verbessern, andererseits aber auch das Debuggen erschweren, da zahlreiche Threads nachverfolgt werden.

Echte Parallelverarbeitung ist nicht immer möglich. Threads müssen manchmal synchronisiert werden. Ein Thread muss möglicherweise auf das Ergebnis eines anderen Threads warten, oder ein Thread benötigt exklusiven Zugriff auf eine Ressource, die von einem anderen Thread verwendet wird. Synchronisierungsprobleme sind eine häufige Ursache von Programmfehlern in Multithreadanwendungen. Es kann passieren, dass Threads auf eine Ressource warten, die nie verfügbar wird. Dies führt zu einem Zustand, der Deadlock genannt wird.

Threads und Prozesse

Threads und Prozesse sind verwandte Konzepte der Informatik. Beide stellen Folgen von Anweisungen dar, die in einer bestimmten Reihenfolge ausgeführt werden müssen. Anweisungen von verschiedenen Threads oder Prozessen können aber parallel ausgeführt werden.

Prozesse werden im Betriebssystem verwaltet und entsprechen dem, was Benutzer als Programme oder Anwendungen sehen. Ein Thread hingegen wird von einem Prozess verwaltet. Aus diesem Grund werden Threads gelegentlich als Lightweightprozesse bezeichnet. Jeder Prozess besteht aus einem oder mehreren Threads.

Die Möglichkeit, mehrere Prozesse auszuführen, versetzt einen Computer in die Lage, mehr als eine Aufgabe gleichzeitig auszuführen. Das Vorhandensein mehrerer Threads versetzt einen Prozess in die Lage, Arbeiten so aufzuteilen, dass sie parallel ausgeführt werden können. Auf einem Computer mit Multiprozessoren können Prozesse oder Threads auf verschiedenen Prozessoren ausgeführt werden. Dies ermöglicht eine echte Parallelverarbeitung.

Tools zum Debuggen von Multithread-Apps

Visual Studio stellt verschiedene Tools für das Debuggen von Multithread-Apps bereit.

Visual Studio stellt auch leistungsstarke Breakpoints und Ablaufverfolgungspunkte bereit, die beim Debuggen von Multithreadanwendungen hilfreich sein können. Verwenden Sie Breakpointbedingungen und -filter, um Breakpoints in einzelnen Threads zu platzieren. Ablaufverfolgungspunkte ermöglichen es Ihnen, die Ausführung des Programms ohne Unterbrechung zu verfolgen, um Probleme wie Deadlocks zu untersuchen. Weitere Informationen finden Sie unter Haltepunktaktionen und Ablaufverfolgungspunkte.

Das Debuggen einer Multithreadanwendung mit einer Benutzeroberfläche kann besonders schwierig sein. Sie könnten erwägen, die Anwendung auf einem zweiten Computer auszuführen und das Remotedebuggen zu verwenden. Weitere Informationen finden Sie unter Remotedebuggen.

In der folgenden Tabelle sind die verfügbaren Informationen und die an jeder Stelle möglichen Aktionen aufgeführt:

Benutzeroberfläche Verfügbare Informationen Ausführbare Aktionen
Dialogfeld An den Prozess anhängen Verfügbare Prozesse, an die angehängt werden kann:

- Prozessname (.exe)
- Prozess-ID-Nummer
- Menüleistentitel
- Typ (Managed v4.0; Managed v2.0, v1.1, v1.0; x86; x64; IA64)
- Benutzername (Kontoname)
- Sitzungsnummer
Auswählen eines Prozesses, an den angehängt werden soll

Auswählen eines Remotecomputers

Ändern des Transporttyps für die Verbindung mit Remotecomputern
Fenster Prozesse Angehängte Prozesse:

- Prozessname
- Prozess-ID-Nummer
- Pfad zur .exe-Datei des Prozesses
- Menüleistentitel
- Zustand (Pause. Wird ausgeführt)
- Debuggen (nativ, verwaltet usw.)
- Transporttyp (standardmäßig, nativ ohne Authentifizierung)
- Transportqualifizierer (Remotecomputer)
Tools:

- Attach (anfügen)
- Detach (trennen)
- Terminate (beenden)

Kontextmenü:

- Attach (anfügen)
- Detach (trennen)
- Nach Beenden des Debuggings trennen
- Terminate (beenden)
Fenster Threads Threads in aktuellem Prozess:

- Thread-ID
- Verwaltete-ID
- Kategorie (Hauptthread, Benutzeroberflächenthread, Remoteprozeduraufruf-Handler oder Arbeitsthread)
- Threadname
- Ort, an dem der Thread erstellt wird
- Priorität
- Affinitätsmaske
- Angehaltene Anzahl
- Prozessname
- Kennzeichenindikator
- Angehaltener Indikator
Tools:

- Suche
- Aufrufliste durchsuchen
- Nur eigenen Code kennzeichnen
- Benutzerdefinierte Modulauswahl kennzeichnen
- Gruppieren nach
- Spalten
- Aufruflisten aufklappen/zuklappen
- Gruppen aufklappen/zuklappen
- Threads einfrieren/reaktivieren

Kontextmenü:

- Threads in Quelle anzeigen
- Zu Thread wechseln
- Ausgeführten Thread einfrieren
- Eingefrorenen Thread reaktivieren
- Thread zur weiteren Überprüfung kennzeichnen
- Kennzeichnung eines Threads aufheben
- Thread umbenennen
- Threads anzeigen und ausblenden

Sonstige Aktionen:

- Aufrufliste für einen Thread in einem DataTip anzeigen
Quellcodefenster Threadindikatoren im linken Bundsteg geben einzelne oder mehrere Threads an (standardmäßig deaktiviert, die Aktivierung erfolgt über das Kontextmenü im Fenster Threads). Kontextmenü:

- Zu Thread wechseln
- Thread zur weiteren Überprüfung kennzeichnen
- Kennzeichnung eines Threads aufheben
Symbolleiste Debugspeicherort - Aktueller Prozess
- Anwendung anhalten
- Anwendung fortsetzen
- Anwendung anhalten und herunterfahren
- Aktueller Thread
- Aktuellen Status des Threadkennzeichens umkehren
- Nur gekennzeichnete Threads anzeigen
- Nur aktuellen Prozess anzeigen
- Aktueller Stapelrahmen
- Zu einem anderen Prozess wechseln
- Anwendung anhalten, fortsetzen oder herunterfahren
- Zu einem anderen Thread im aktuellem Prozess wechseln
- Zu einem anderen Stapelrahmen in aktuellem Thread wechseln
- Aktuelle Threads kennzeichnen bzw. Kennzeichnung aufheben
- Nur gekennzeichnete Threads anzeigen
- Nur den aktuellen Prozess anzeigen
Fenster Parallele Stapel - Aufruflisten für mehrere Threads in einem Fenster.
- Aktiver Stapelrahmen für jeden Thread.
- Aufrufer und Aufgerufene für die einzelnen Methoden.
- Deadlockerkennung
- Bestimmte Threads herausfiltern
- Herausfiltern externer Codestapel
- Zur Aufgabenansicht wechseln
- Thread kennzeichnen bzw. Kennzeichnung aufheben
- Zoomen
- Kopieren von Stapelrahmen
- Speichern/Exportieren aller Stapel als Bild
Fenster Parallele Überwachung - Die Kennzeichenspalte, in der Sie einen Thread markieren können, der besondere Aufmerksamkeit erhalten soll.
- Die Framespalte, in der ein Pfeil den ausgewählten Frame angibt.
- Eine konfigurierbare Spalte, in der der Computer, der Prozess, die Kachel, die Aufgabe und der Thread angezeigt werden können.
- Thread kennzeichnen bzw. Kennzeichnung aufheben
- Nur gekennzeichnete Threads anzeigen
- Frames wechseln
- Spalte sortieren
- Threads gruppieren
- Threads einfrieren oder reaktivieren
- Daten im parallelen Überwachungsfenster exportieren
Fenster Aufgaben - Informationen zu Task-Objekten anzeigen, einschließlich der Aufgaben-ID, des Aufgabenstatus (geplant, ausgeführt, wartend, blockiert) und der der Aufgabe zugewiesenen Threads.
- Aktuelle Position in der Aufrufliste.
- Zur Erstellungszeit an die Aufgabe übergebener Delegat
- Zur aktuellen Aufgabe wechseln
- Aufgabe kennzeichnen oder Kennzeichnung aufheben
- Aufgabe einfrieren oder reaktivieren
Fenster GPU-Threads - Die Kennzeichenspalte, in der Sie einen Thread markieren können, der besondere Aufmerksamkeit erhalten soll.
- Die Spalte für den aktuellen Thread, in der ein gelber Pfeil den aktuellen Thread kennzeichnet.
- Die Spalte Threadanzahl, in der die Anzahl von Threads an derselben Position angezeigt wird.
- Die Spalte Zeile, in der die Codezeile angezeigt wird, in der sich die jeweilige Threadgruppe befindet.
- Die Spalte Adresse, in der die Anweisungsadresse angezeigt wird, in der sich die jeweilige Threadgruppe befindet.
- Die Spalte Speicherort, in der der Ort im Code die Adresse angegeben ist.
- Die Spalte Status, in der angegeben ist, ob der Thread aktiv oder blockiert ist.
- Die Spalte Kachel, in der der Kachelindex für die Threads in der Zeile angezeigt wird.
- Wechseln zu einem anderen Thread
- Bestimmte Kachel und bestimmten Thread anzeigen
- Spalte ein- oder ausblenden
- Nach Spalte sortieren
- Threads gruppieren
- Threads einfrieren oder reaktivieren
- Thread kennzeichnen bzw. Kennzeichnung aufheben
- Nur gekennzeichnete Threads anzeigen