Freigeben über


Tipps zum Debuggen von Threads

Dieser Artikel enthält hilfreiche Informationen zum Debuggen von Threads, einschließlich Informationen zum Festlegen von Threadnamen für nativen und verwalteten Code.

C/C++-Tipps

Im Folgenden finden Sie einige Tipps, die beim Debuggen von Threads in systemeigenem Code hilfreich sein können:

  • Sie können den Inhalt des Threadinformationsblocks anzeigen, indem Sie @TIB im Überwachungsfenster oder im Dialogfeld Schnellüberwachung eingeben.

  • Sie können den letzten Fehlercode für den aktuellen Thread anzeigen, indem Sie @Err im Überwachungsfenster oder im Dialogfeld Schnellüberwachung eingeben.

  • Funktionen der C-Laufzeitbibliotheken (CRT) können hilfreich beim Debuggen von Multithreadanwendungen sein. Weitere Informationen finden Sie unter _malloc_dbg.

Festlegen eines Threadnamens in C/C++

Das Benennen von Threads ist in allen Editionen von Visual Studio möglich. Die Benennung von Threads ist hilfreich, um beim Debuggen eines ausgeführten Prozesses relevante Threads im Fenster Threads zu identifizieren. Aussagekräftige Namen für Threads können auch nützlich sein, wenn Sie nachträgliches Debuggen über die Überprüfung von Absturzabbildern durchführen und Leistungserfassungen mithilfe verschiedener Tools analysieren.

Möglichkeiten zum Festlegen eines Threadnamens

Es gibt zwei Möglichkeiten, einen Threadnamen festzulegen. Bei der ersten Möglichkeit wird die Funktion SetThreadDescription verwendet. Bei der zweiten wird eine bestimmte Ausnahme ausgelöst, während der Visual Studio-Debugger an den Prozess angefügt ist. Jeder Ansatz hat Vor- und Nachteile. Die Verwendung von SetThreadDescription wird ab Windows 10, Version 1607 oder Windows Server 2016 unterstützt.

Beachten Sie, dass beide Ansätze bei Bedarf zusammen verwendet werden können, da ihre Mechanismen voneinander unabhängig sind.

Festlegen eines Threadnamens mithilfe von SetThreadDescription

Vorteile:

  • Threadnamen sind beim Debuggen in Visual Studio unabhängig davon sichtbar, ob der Debugger zum Zeitpunkt des Aufrufs von „SetThreadDescription“ an den Prozess angefügt war.
  • Threadnamen sind sichtbar, wenn Sie nachträgliches Debuggen durch Laden eines Absturzabbilds in Visual Studio ausführen.
  • Threadnamen werden auch angezeigt, wenn Sie andere Tools verwenden, z. B. den WinDbg-Debugger und die Leistungsanalyse Windows Performance Analyzer.

Zu beachten:

  • Threadnamen werden nur in Visual Studio 2017, Version 15.6 und höheren Versionen angezeigt.
  • Wenn Sie nachträgliches Debuggen für eine Absturzabbilddatei ausführen, werden Threadnamen nur angezeigt, wenn der Absturz unter Windows 10, Version 1607, Windows Server 2016 oder neueren Windows-Versionen aufgetreten ist.

Beispiel:

#include <windows.h>
#include <processthreadsapi.h>

int main()
{
    HRESULT r;
    r = SetThreadDescription(
        GetCurrentThread(),
        L"ThisIsMyThreadName!"
    );

    return 0;
}

Festlegen eines Threadnamens durch Auslösen einer Ausnahme

Eine andere Möglichkeit zum Festlegen eines Threadnamens in Ihrem Programm besteht darin, dem Visual Studio-Debugger den gewünschten Threadnamen mitzuteilen, indem eine speziell konfigurierte Ausnahme ausgelöst wird.

Vorteile:

  • Dies funktioniert in allen Visual Studio-Versionen.

Zu beachten:

  • Dies funktioniert nur, wenn der Debugger zu dem Zeitpunkt angefügt ist, zu dem die ausnahmebasierte Methode verwendet wird.
  • Threadnamen, die mit dieser Methode festgelegt werden, sind in Absturzabbildern oder Leistungsanalysetools nicht verfügbar.

Beispiel:

Mit der unten gezeigten SetThreadName-Funktion wird dieser ausnahmebasierte Ansatz veranschaulicht. Der Threadname wird automatisch in den Thread kopiert, damit der Arbeitsspeicher für den threadName-Parameter nach Abschluss des SetThreadName-Aufrufs freigegeben werden kann.

//
// Usage: SetThreadName ((DWORD)-1, "MainThread");
//
#include <windows.h>
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
    DWORD dwType; // Must be 0x1000.
    LPCSTR szName; // Pointer to name (in user addr space).
    DWORD dwThreadID; // Thread ID (-1=caller thread).
    DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
void SetThreadName(DWORD dwThreadID, const char* threadName) {
    THREADNAME_INFO info;
    info.dwType = 0x1000;
    info.szName = threadName;
    info.dwThreadID = dwThreadID;
    info.dwFlags = 0;
#pragma warning(push)
#pragma warning(disable: 6320 6322)
    __try{
        RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
    }
    __except (EXCEPTION_EXECUTE_HANDLER){
    }
#pragma warning(pop)
}

Festlegen eines Threadnamens in verwaltetem Code

Das Benennen von Threads ist in allen Editionen von Visual Studio möglich. Das Benennen von Threads ist hilfreich beim Verfolgen von Threads im Fenster Threads.

Um einen Threadnamen in verwaltetem Code festzulegen, verwenden Sie die Name-Eigenschaft.

Beispiel

public class Needle
{
    // This method will be called when the thread is started.
    public void Baz()
    {
        Console.WriteLine("Needle Baz is running on another thread");
    }
}

public void Main()
{
    Console.WriteLine("Thread Simple Sample");
    Needle oNeedle = new Needle();
    // Create a Thread object.
    System.Threading.Thread oThread = new System.Threading.Thread(oNeedle.Baz);
    // Set the Thread name to "MyThread".
    oThread.Name = "MyThread";
    // Starting the thread invokes the ThreadStart delegate
    oThread.Start();
}