C++: _beginthreadex, thread function name not showing in Visual Studio Threads window

3.6k Views Asked by At

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?

2

There are 2 best solutions below

0
On BEST ANSWER

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)
   {
   }
}
3
On

There is no particular advantage with using _beginthreadex over CreateThread. The CRT functions would eventually call CreateThread only.

You should read: