1

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?

Richard Chambers
  • 14,509
  • 3
  • 62
  • 86
dario_ramos
  • 6,536
  • 7
  • 50
  • 104

2 Answers2

3

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)
   {
   }
}
Michael Burr
  • 311,791
  • 49
  • 497
  • 724
1

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

You should read:

Community
  • 1
  • 1
Ajay
  • 16,823
  • 9
  • 50
  • 94
  • Excuse me, but all the links you provide advocate the use of _beginthreadex. They say that it's less prone to memory leaks, and that is very important in my app, which is extensively multithreaded – dario_ramos Aug 18 '11 at 17:29
  • In today's compiler/linker and the library, `_beginthreadex` gives no added advantage. Don't talk about VC6, which is very much outdated. – Ajay Aug 18 '11 at 17:50
  • My code, though rarely, interacts with VC6 binaries, so I'd rather play it safe – dario_ramos Aug 18 '11 at 17:55