C++:_beginthreadex,线程函数名称未显示在 Visual Studio 线程窗口中

发布于 2024-11-30 19:04:32 字数 382 浏览 1 评论 0原文

我最近了解到 ::_beginthreadex() 始终优于 ::CreateThread(),因此我更改了所有使用 ::CreateThread()< 的调用/代码>。

唯一的缺点是我不再在 Visual Studio 的 Threads 窗口中看到线程函数的名称,因此很难快速识别线程。我假设这是在我使用 ::CreateThread() 时由调试器自动完成的,因为参数完全相同,我只是更改了所使用函数的名称。

有没有办法继续使用 ::_beginthreadex() 并在 Visual Studio 的 Threads 窗口中查看线程的名称?

I recently learnt that ::_beginthreadex() is always preferable to ::CreateThread(), so I changed all my calls that used ::CreateThread().

The only downside is that I no longer see the thread function's name in Visual Studio's Threads window making it hard to quickly identify threads. I assume this was somehow done automatically by the debugger when I used ::CreateThread(), since the parameters are exactly the same, I just changed the name of the function used.

Is there any way to keep using ::_beginthreadex() and to see the thread's name in the Threads window of Visual Studio?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜心小果奶 2024-12-07 19:04:32

发生这种情况是因为 _beginthreadex() 使用其自己的线程函数调用 CreateThread(),该函数调用您指定的线程函数(因此调试器使用 _threadstartex 函数) name - _beginthreadex() 调用的名称)。

您可以使用 MSDN 中的 SetThreadName() 示例自行手动设置线程名称。您可能想要做的是为 _beginthreadex() 创建自己的包装器,可能看起来像这样:

uintptr_t startthreadex(
    void* security, 
    unsigned stacksize, 
    unsigned (__stdcall * threadproc) (void *), 
    void* args, 
    unsigned flags, 
    unsigned * pThread_id,
    char* thread_name)
{
    unsigned alt_thread_id;

    if (!pThread_id) {
        pThread_id = & alt_thread_id;
    }

    uintptr_t result = _beginthreadex(security, stacksize, threadproc, args, flgas, pThread_id);

    if (result == 0) return result;

    SetThreadName( *pThread_id, thread_name);
}

现在您可以调用 startthreadex() 而不是 _beginthreadex() 并向其传递一个线程名称。这样做的一个小优点是,如果您使用相同的函数来运行多个线程,您可以轻松地为它们指定唯一的名称,以反映传递给线程的参数或其他名称。

如果您希望线程名称自动采用线程过程函数名称作为调试器的线程名称,您可以创建一个包装宏来字符串化函数名称参数(它所需要的只是另一级间接或解决任何问题.. .)。

这是 SetThreadName() (来自 http://msdn .microsoft.com/en-us/library/xcb2z8hs.aspx):

//
// Usage: SetThreadName (-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, char* threadName)
{
   THREADNAME_INFO info;
   info.dwType = 0x1000;
   info.szName = threadName;
   info.dwThreadID = dwThreadID;
   info.dwFlags = 0;

   __try
   {
      RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
   }
   __except(EXCEPTION_EXECUTE_HANDLER)
   {
   }
}

This happens because _beginthreadex() calls CreateThread() with its own thread function that calls the one you specify (so the debugger uses the _threadstartex function name - the one that _beginthreadex() invokes).

You can manually set the thread name yourself using the SetThreadName() example from MSDN. What you might want to do is create your own wrapper for _beginthreadex() that maybe looks something like:

uintptr_t startthreadex(
    void* security, 
    unsigned stacksize, 
    unsigned (__stdcall * threadproc) (void *), 
    void* args, 
    unsigned flags, 
    unsigned * pThread_id,
    char* thread_name)
{
    unsigned alt_thread_id;

    if (!pThread_id) {
        pThread_id = & alt_thread_id;
    }

    uintptr_t result = _beginthreadex(security, stacksize, threadproc, args, flgas, pThread_id);

    if (result == 0) return result;

    SetThreadName( *pThread_id, thread_name);
}

Now you can call startthreadex() instead of _beginthreadex() and pass it a thread name. A small advantage to this is that if you use the same function to run several threads, you can easily give them each unique names that reflect the parameters passed ot the thread or whatever.

If you want the thread name to automatically take be the thread proc function name as the debugger's thread name, you could make a wrapper macro that stringizes the function name parameter (all it takes is another level of indirection or to to solve any problem...).

Here's SetThreadName() (it's from http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx):

//
// Usage: SetThreadName (-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, char* threadName)
{
   THREADNAME_INFO info;
   info.dwType = 0x1000;
   info.szName = threadName;
   info.dwThreadID = dwThreadID;
   info.dwFlags = 0;

   __try
   {
      RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
   }
   __except(EXCEPTION_EXECUTE_HANDLER)
   {
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文