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 systemeigene und verwalteten Code.

C/C++-Tipps

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

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

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

  • C Run-Time Libraries (CRT)-Funktionen können zum Debuggen einer Multithreadanwendung hilfreich sein. Weitere Informationen finden Sie unter _malloc_dbg.

Festlegen eines Threadnamens in C/C++

Threadbenennung ist in jeder Edition von Visual Studio möglich. Threadbenennung ist nützlich, um Threads zu identifizieren, die beim Debuggen eines ausgeführten Prozesses im Threads-Fenster von Interesse sind. Das Verwenden von erkennbar benannten Threads kann auch hilfreich sein, wenn ein Post-Mortem-Debugging durch die Überprüfung von Crash-Dumps durchgeführt wird, und bei der Analyse von Performance-Messungen mit verschiedenen Tools.

Möglichkeiten zum Festlegen eines Threadnamens

Es gibt zwei Möglichkeiten zum Festlegen eines Threadnamens. Die erste Möglichkeit ist über die SetThreadDescription Funktion. Der zweite Vorgang besteht darin, eine bestimmte Ausnahme auszuwerfen, während der Visual Studio-Debugger an den Prozess angefügt ist. Jeder Ansatz hat Vorteile und Vorbehalte. Die Verwendung von SetThreadDescription wird ab Windows 10, Version 1607, oder Windows Server 2016 unterstützt.

Es lohnt sich zu beachten, dass beide Ansätze bei Bedarf zusammen verwendet werden können, da die Mechanismen, mit denen sie arbeiten, voneinander unabhängig sind.

Festlegen eines Threadnamens mithilfe von SetThreadDescription

Vorteile:

  • Threadnamen sind beim Debuggen in Visual Studio sichtbar, unabhängig davon, ob der Debugger zum Zeitpunkt des Aufrufs von SetThreadDescription an den Prozess angefügt wurde.
  • Threadnamen sind beim nachträglichen Debuggen durch Laden eines Speicherabbilds in Visual Studio sichtbar.
  • Threadnamen sind auch bei der Verwendung anderer Tools sichtbar, z. B. dem WinDbg-Debugger und dem Windows Performance Analyzer.

Zu beachten:

  • Threadnamen sind nur in Visual Studio 2017, Version 15.6 und höher, sichtbar.
  • Beim Post-Mortem-Debugging einer Crash-Dump-Datei sind Threadnamen nur sichtbar, wenn der Absturz auf Windows 10 Version 1607, Windows Server 2016 oder einer neueren Version von Windows erstellt wurde.

Example:

#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 weitere Möglichkeit zum Festlegen eines Threadnamens in Ihrem Programm besteht darin, den gewünschten Threadnamen mit dem Visual Studio-Debugger zu kommunizieren, indem eine speziell konfigurierte Ausnahme ausgelöst wird.

Vorteile:

  • Funktioniert in allen Versionen von Visual Studio.

Zu beachten:

  • Funktioniert nur, wenn der Debugger zum Zeitpunkt der Verwendung der ausnahmebasierten Methode angefügt ist.
  • Threadnamen, die mit dieser Methode festgelegt werden, sind in Dumps oder Leistungsanalysetools nicht verfügbar.

Example:

Die SetThreadName unten gezeigte Funktion veranschaulicht diesen ausnahmebasierten Ansatz. Beachten Sie, dass der Threadname automatisch in den Thread kopiert wird, damit der Speicher für den threadName Parameter freigegeben werden kann, nachdem der SetThreadName Aufruf abgeschlossen wurde.

//
// 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

Threadbenennung ist in jeder Edition von Visual Studio möglich. Threadbenennung ist nützlich, um Threads im Threads-Fenster nachzuverfolgen.

Verwenden Sie die Name Eigenschaft, um einen Threadnamen in verwaltetem Code festzulegen.

Example

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();
}