如何:在本机代码中设置线程名称How to: Set a Thread Name in Native Code

在 Visual Studio 的任何版本中都可以使用线程命名功能。Thread naming is possible in any edition of Visual Studio. 线程命名功能可用于标识的感兴趣的线程线程窗口调试正在运行的进程时。Thread naming is useful for identifying threads of interest in the Threads window when debugging a running process. 具有 recognizably 名为线程也会有所帮助时执行事后调试通过崩溃转储检查和分析性能捕获使用各种工具。Having recognizably-named threads can also be helpful when performing post-mortem debugging via crash dump inspection and when analyzing performance captures using various tools.

如何设置线程名称Ways to set a thread name

有两种方法来设置线程名称。There are two ways to set a thread name. 第一种是通过SetThreadDescription函数。The first is via the SetThreadDescription function. 第二个是通过 Visual Studio 调试器附加到进程时引发特定异常。The second is by throwing a particular exception while the Visual Studio debugger is attached to the process. 每种方法都有优点和需要注意的问题。Each approach has benefits and caveats.

值得注意的是_同时_方法可以一起使用,如果需要,因为它们的工作所依据的机制是相互独立。It is worth noting that both approaches can be used together, if desired, since the mechanisms by which they work are independent of each other.

通过设置线程名称 SetThreadDescriptionSet a thread name by using SetThreadDescription

优点:Benefits:

  • 在 Visual Studio 中,而不考虑在调试器已附加到进程调用 SetThreadDescription 时进行调试时,线程名称是可见的。Thread names are visible when debugging in Visual Studio, regardless of whether or not the debugger was attached to the process at the time that SetThreadDescription is invoked.
  • 执行事后通过加载 Visual Studio 中的故障转储调试时,线程名称是可见的。Thread names are visible when performing post-mortem debugging by loading a crash dump in Visual Studio.
  • 线程名称也是可见时使用其他工具,如WinDbg调试器并Windows Performance Analyzer性能分析器。Thread names are also visible when using other tools, such as the WinDbg debugger and the Windows Performance Analyzer performance analyzer.

注意:Caveats:

  • 线程名称仅显示在 Visual Studio 2017 版本 15.6 及更高版本。Thread names are only visible in Visual Studio 2017 version 15.6 and later.
  • 事后调试崩溃转储文件,线程名称时,仅在 Windows 10 版本 1607年中,Windows Server 2016 或更高版本的 Windows 上创建在崩溃时可见。When post-mortem debugging a crash dump file, thread names are only visible if the crash was created on Windows 10 version 1607, Windows Server 2016 or later versions of Windows.

示例:Example:

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

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

    return 0;
}

通过引发异常来设置线程名称Set a thread name by throwing an exception

若要在程序中设置线程名称的另一种方法是通过引发专门配置异常到 Visual Studio 调试器通信所需的线程名称。Another way to set a thread name in your program is to communicate the desired thread name to the Visual Studio debugger by throwing a specially-configured exception.

优点:Benefits:

  • 所有版本的 Visual Studio 中的工作原理。Works in all versions of Visual Studio.

注意:Caveats:

  • 仅适用于将调试器附加于的基于异常的方法的时间。Only works if the debugger is attached at the time the exception-based method is used.
  • 使用此方法设置线程名称在转储或性能分析工具中将不可用。Thread names set by using this method will not be available in dumps or performance analysis tools.

示例:Example:

SetThreadName函数如下所示演示此基于异常的方法。The SetThreadName function shown below demonstrates this exception-based approach. 请注意,线程名称将自动复制到线程,以便为内存threadName参数可以释放后SetThreadName调用完成。Note that the thread name will be automatically copied to the thread, so that the memory for the threadName parameter can be released after the SetThreadName call is completed.

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

请参阅See Also

调试多线程应用程序Debug Multithreaded Applications
查看调试器中的数据Viewing Data in the Debugger
如何:在托管代码中设置线程名称How to: Set a Thread Name in Managed Code