Exemplarische Vorgehensweise: Debuggen einer Multithread-App mithilfe des Fensters „Threads“ (C#, Visual Basic, C++)

Mehrere Visual Studio-Benutzeroberflächenelemente helfen Ihnen beim Debuggen von Multithread-Apps. In diesem Artikel werden Multithread-Debugfunktionen im Code-Editor-Fenster, auf der Symbolleiste Debugspeicherort und im Fenster Threads vorgestellt. Weitere Informationen zu anderen Tools zum Debuggen von Multithread-Apps finden Sie unter Erste Schritte beim Debuggen von Multithread-Apps.

Das Durcharbeiten dieses Tutorials dauert nur einige Minuten und vermittelt Ihnen die Grundlagen des Debuggens von Multithread-Apps.

Erstellen eines Multithread-App-Projekts

Erstellen Sie das folgende Multithread-App-Projekt für die Verwendung in diesem Tutorial:

  1. Öffnen Sie Visual Studio, und erstellen Sie ein neues Projekt.

    Wenn das Startfenster nicht geöffnet ist, klicken Sie auf Datei>Startfenster.

    Wählen Sie im Startfenster Neues Projekt aus.

    Wählen Sie im Startfenster Neues Projekt erstellen aus.

    Geben Sie im Fenster Neues Projekt erstellen im Suchfeld Konsole ein. Wählen Sie anschließend in der Liste der Sprachen C# oder C++ und dann in der Liste der Plattformen Windows aus.

    Nachdem Sie die Sprach- und Plattformfilter angewandt haben, wählen Sie Konsolen-App für .NET Core, .NET 5 (und höher) oder C++ und dann Weiter aus.

    Hinweis

    Wenn die richtige Vorlage nicht angezeigt wird, öffnen Sie unter Tools>Tools und Features abrufen... den Visual Studio-Installer. Wählen Sie die Workload .NET-Desktopentwicklung oder Desktopentwicklung mit C++ und anschließend Ändern aus.

    Geben Sie im Fenster Neues Projekt konfigurieren einen Namen ein, oder verwenden Sie im Feld Projektname den Standardnamen. Klicken Sie anschließend je nach verfügbarer Option entweder auf Weiter oder auf Erstellen.

    Wählen Sie für .NET Core oder .NET 5+ entweder das empfohlene Zielframework oder .NET 8 aus, und klicken Sie dann auf Erstellen.

    Ein neues Konsolenprojekt wird angezeigt. Nachdem das Projekt erstellt wurde, wird eine Quelldatei angezeigt. Abhängig von der ausgewählten Programmiersprache hat die Quelldatei die Bezeichnung Program.cs oder MyThreadWalkthroughApp.cpp.

  2. Ersetzen Sie den Code in der Quelldatei durch den C#- oder C++-Beispielcode aus Erste Schritte beim Debuggen von Multithread-Apps.

  3. Wählen Sie Datei>Alle speichern aus.

Debugging starten

  1. Suchen Sie im Quellcode nach den folgenden Zeilen:

    Thread.Sleep(3000);
    Console.WriteLine();
    
  2. Legen Sie einen Breakpoint in der Zeile Console.WriteLine(); fest, indem Sie im linken Bundsteg klicken oder die Zeile auswählen und F9 drücken.

    Der Breakpoint wird als roter Kreis im linken Bundsteg neben der Codezeile angezeigt.

  3. Wählen Sie Debuggen>Debuggen starten aus, oder drücken Sie F5.

    Die App wird im Debugmodus gestartet und am Breakpoint angehalten.

  4. Öffnen Sie im Unterbrechungsmodus das Fenster Threads, indem Sie Debuggen>Windows>Threads auswählen. Sie müssen sich in einer Debugsitzung befinden, um Threads und andere Debugfenster öffnen oder anzeigen zu können.

Untersuchen von Threadmarkern

  1. Suchen Sie im Quellcode nach der Zeile Console.WriteLine();.

    1. Klicken Sie mit der rechten Maustaste in das Fenster Threads, und wählen Sie im Menü Threads in Quelle anzeigenShow Threads in Source aus.

    Der Bundsteg neben der Quellcodezeile zeigt nun ein Threadmarkersymbol an Thread Marker. Der Threadmarker gibt an, dass ein Thread an dieser Position angehalten wurde. Wenn an der Position mehrere angehaltene Threads vorhanden sind, wird das Symbol für multiple threads angezeigt.

  2. Zeigen Sie mit dem Mauszeiger auf den Threadmarker. Ein DataTip wird angezeigt, in dem der Name und die Thread-ID für den beendeten Thread oder die beendeten Threads angezeigt werden. Die Threadnamen können <No Name> lauten.

    Tipp

    Um namenlose Threads zu identifizieren, können Sie diese im Fenster Threads umbenennen. Klicken Sie mit der rechten Maustaste auf den Thread, und wählen Sie Umbenennen aus.

  3. Klicken Sie mit der rechten Maustaste auf den Threadmarker im Quellcode, um die verfügbaren Optionen im Kontextmenü anzuzeigen.

Kennzeichnen von Threads und Aufheben der Kennzeichnung

Sie können Threads kennzeichnen, um die Threads nachzuverfolgen, auf die Sie besonders achten möchten.

Kennzeichnen Sie Threads im Quellcode-Editor oder im Fenster Threads, oder heben Sie dort die Kennzeichnung auf. Wählen Sie, ob nur gekennzeichnete Threads oder alle Threads in der Symbolleiste Debugspeicherort oder im Fenster Threads angezeigt werden sollen. Die Auswahl an einer beliebigen Position wirkt sich auf alle Positionen aus.

Kennzeichnen von Threads im Quellcode und Aufheben der Kennzeichnung

  1. Öffnen Sie die Symbolleiste Debugspeicherort, indem Sie Anzeigen>Symbolleisten>Debugspeicherort auswählen. Sie können auch mit der rechten Maustaste im Symbolleistenbereich klicken und dann Debugspeicherort auswählen.

  2. Die Symbolleiste Debugspeicherort weist drei Felder auf: Prozess, Thread und Stapelrahmen. Öffnen Sie die Liste Thread, und beachten Sie, wie viele Threads vorhanden sind. In der Liste Thread wird der derzeit ausgeführte Thread durch ein > -Symbol gekennzeichnet.

  3. Zeigen Sie im Quellcodefenster auf ein Threadmarkersymbol im Bundsteg, und wählen Sie das Flagsymbol (oder eines der leeren Flagsymbole) im DataTip aus. Das Flagsymbol wird rot.

    Sie können auch mit der rechten Maustaste auf ein Threadmarkersymbol klicken, auf Flag zeigen und dann einen Thread auswählen, der über das Kontextmenü gekennzeichnet werden soll.

  4. Wählen Sie auf der Symbolleiste Debugspeicherort das Symbol Nur gekennzeichnete Threads anzeigenShow Flagged Threads rechts neben dem Feld Thread aus. Das Symbol ist ausgegraut, es sei denn, mindestens ein Thread ist gekennzeichnet.

    Nur der gekennzeichnete Thread wird jetzt in der Dropdownliste Thread auf der Symbolleiste angezeigt. Um erneut alle Threads anzuzeigen, aktivieren Sie das Symbol Nur gekennzeichnete Threads anzeigen erneut.

    Tipp

    Nachdem Sie einige Threads gekennzeichnet haben, können Sie den Cursor im Code-Editor platzieren, mit der rechten Maustaste klicken und Gekennzeichnete Threads bis zum Cursor ausführen auswählen. Stellen Sie sicher, dass Sie Code auswählen, der von allen gekennzeichneten Threads erreicht wird. Gekennzeichnete Threads bis zum Cursor ausführen hält Threads in der ausgewählten Codezeile an, um die Ausführungsreihenfolge durch Einfrieren und Reaktivieren von Threads einfacher zu steuern.

  5. Um den gekennzeichneten bzw. nicht gekennzeichneten Status des aktuell ausgeführten Threads umzuschalten, wählen Sie auf der linken Seite der Schaltfläche Nur gekennzeichnete Threads anzeigen die Schaltfläche Flagzustand des aktuellen Threads umschalten der Symbolleiste für ein einzelnes Flag aus. Das Kennzeichnen des aktuellen Threads ist hilfreich für die Suche nach dem aktuellen Thread, wenn nur gekennzeichnete Threads angezeigt werden.

  6. Um die Kennzeichnung für einen Thread zu entfernen, bewegen Sie den Mauszeiger über den Threadmarker im Quellcode, und wählen Sie das rote Flagsymbol aus, um es zu löschen, oder klicken Sie mit der rechten Maustaste auf den Threadmarker und wählen dann Kennzeichnung aufheben aus.

Kennzeichnen und Aufheben der Kennzeichnung von Threads im Fenster „Threads“

Im Fenster Threads werden neben gekennzeichneten Threads rote Flagsymbole angezeigt, während nicht gekennzeichnete Threads, wenn Sie angezeigt werden, leere Kontursymbole aufweisen.

Threads Window

Wählen Sie ein Flagsymbol aus, um den Threadzustand je nach aktuellem Status in gekennzeichnet oder nicht gekennzeichnet zu ändern.

Sie können auch mit der rechten Maustaste auf eine Zeile klicken und Kennzeichnen, Kennzeichnung aufheben oder Kennzeichnung aller Threads aufheben im Kontextmenü auswählen.

Die Symbolleiste des Fensters Threads umfasst außerdem eine Schaltfläche Nur gekennzeichnete Threads anzeigen, bei der es sich um das rechte der beiden Flagsymbole handelt. Sie funktioniert genauso wie die Schaltfläche auf der Symbolleiste Debugspeicherort, und beide Schaltflächen steuern die Anzeige an beiden Speicherorten.

Features des Fensters „Andere Threads“

Wählen Sie im Fenster Threads die Kopfzeile einer beliebigen Spalte aus, um die Threads nach dieser Spalte zu sortieren. Klicken Sie erneut, um die Sortierreihenfolge umzukehren. Wenn alle Threads angezeigt werden, werden die Threads durch Auswählen der Flagsymbolspalte nach dem Status „Gekennzeichnet“ oder „Nicht gekennzeichnet“ sortiert.

Die zweite Spalte des Fensters Threads (ohne Kopfzeile) ist die Spalte Aktueller Thread. Ein gelber Pfeil in dieser Spalte markiert den aktuellen Ausführungspunkt.

Die Spalte Position zeigt an, wo die einzelnen Threads im Quellcode vorkommen. Wählen Sie den Erweiterungspfeil neben dem Eintrag Position aus, oder zeigen Sie auf den Eintrag, um eine partielle Aufrufliste für diesen Thread anzuzeigen.

Tipp

Um eine grafische Ansicht der Aufruflisten für Threads zu erhalten, verwenden Sie das Fenster Parallele Stapel. Wählen Sie zum Öffnen des Fensters während des Debuggens Debuggen>Windows>Parallele Stapel aus.

Neben Kennzeichnen, Kennzeichnung aufheben und Kennzeichnung aller Threads aufheben enthält das Kontextmenü für Thread-Elemente Folgendes:

  • Die Schaltfläche Threads in Quelle anzeigen.
  • Hexadezimale Anzeige: Ändert die Thread-IDs im Fenster Threads aus einem dezimalen in ein hexadezimales Format.
  • Zu Thread wechseln: Schaltet die Ausführung sofort auf diesen Thread um.
  • Umbenennen: Ändert den Threadnamen.
  • Die Befehle Einfrieren und Reaktivieren.

Einfrieren und Reaktivieren der Threadausführung

Sie können Threads einfrieren und reaktivieren oder anhalten und fortsetzen, um die Reihenfolge zu steuern, in der die Threads Aufgaben ausführen. Das Einfrieren und Reaktivieren von Threads kann Ihnen helfen, Parallelitätsprobleme zu beheben, z. B. Deadlocks und Racebedingungen.

Tipp

Wenn Sie einem einzelnen Thread folgen möchten, ohne andere Threads einzufrieren (dabei handelt es sich ebenfalls um ein häufiges Debugszenario), finden Sie weitere Informationen unter Erste Schritte beim Debuggen von Multithread-Anwendungen.

So fixieren Sie Threads und heben die Fixierung auf:

  1. Klicken Sie im Fenster Threads mit der rechten Maustaste auf einen beliebigen Thread, und klicken Sie dann auf Einfrieren. Ein Symbol Anhalten in der Spalte Aktueller Thread zeigt an, dass der Thread eingefroren ist.

  2. Wählen Sie Spalten in der Symbolleiste des Fensters Threads aus, und wählen Sie dann Angehaltene Anzahl aus, um die Spalte Angehaltene Anzahl anzuzeigen. Der Wert für „Angehaltene Anzahl“ für den eingefrorenen Thread ist 1.

  3. Klicken Sie mit der rechten Maustaste auf den eingefrorenen Thread, und klicken Sie dann auf Reaktivieren.

    Das Symbol Anhalten wird nicht mehr angezeigt, und der Wert von Angehaltene Anzahl ändert sich in 0.

Wechseln zu einem anderen Thread

Wenn Sie versuchen, zu einem anderen Thread zu wechseln, wird möglicherweise ein Fenster Die Anwendung befindet sich im Unterbrechungsmodus angezeigt. Dieses Fenster informiert sie, dass der Thread keinen Code aufweist, den der aktuelle Debugger anzeigen kann. Beispielsweise debuggen Sie verwalteten Code, aber der Thread ist nativer Code. Das Fenster enthält Vorschläge zur Behebung des Problems.

So wechseln Sie zu einem anderen Thread:

  1. Notieren Sie sich im Fenster Threads die aktuelle Thread-ID, bei der es sich um den Thread mit einem gelben Pfeil in der Spalte Aktueller Thread handelt. Sie möchten zurück zu diesem Thread wechseln, um Ihre App fortzusetzen.

  2. Klicken Sie mit der rechten Maustaste auf einen anderen Thread, und wählen Sie aus dem Kontextmenü Zu Thread wechseln aus.

  3. Beachten Sie, dass sich die Position des gelben Pfeils im Fenster Threads geändert hat. Der ursprüngliche aktuelle Threadmarker bleibt ebenfalls (als Kontur) erhalten.

    Sehen Sie sich die QuickInfo für den Threadmarker im Quellcode-Editor an, und klicken Sie in der Dropdownliste Thread auf die Symbolleiste Debugspeicherort. Beachten Sie, dass sich der aktuelle Thread auch dort geändert hat.

  4. Wählen Sie auf der Symbolleiste Debugspeicherort einen anderen Thread aus der Liste Thread aus. Beachten Sie, dass sich der aktuelle Thread auch an den anderen beiden Positionen ändert.

  5. Klicken Sie im Quellcode-Editor mit der rechten Maustaste auf einen Threadmarker, zeigen Sie auf Zu Thread wechseln, und wählen Sie einen anderen Thread aus der Liste aus. Beobachten Sie, dass sich der aktuelle Thread an allen drei Positionen ändert.

Mit dem Threadmarker im Quellcode können Sie nur zu Threads wechseln, die an der jeweiligen Position angehalten wurden. Über das Threadfenster und die Symbolleiste Debugspeicherort können Sie zu jedem beliebigen Thread wechseln.

Sie haben nun die Grundlagen des Debuggens von Multithread-Apps kennengelernt. Sie können Threads mithilfe des Fensters Threads, der Liste Thread auf der Symbolleiste Debugspeicherort oder mit Threadmarkern im Quellcode-Editor beobachten, kennzeichnen bzw. ihre Kennzeichnung aufheben und einfrieren bzw. reaktivieren.