Windows threading: _beginthread vs _beginthreadex vs CreateThread C++

C++CMultithreadingWinapi

C++ Problem Overview


What's a better way to start a thread, _beginthread, _beginthreadx or CreateThread?

I'm trying to determine what are the advantages/disadvantages of _beginthread, _beginthreadex and CreateThread. All of these functions return a thread handle to a newly created thread, I already know that CreateThread provides a little extra information when an error occurs (it can be checked by calling GetLastError)... but what are some things I should consider when I'm using these functions?

I'm working with a windows application, so cross-platform compatibility is already out of the question.

I have gone through the msdn documentation and I just can't understand, for example, why anybody would decide to use _beginthread instead of CreateThread or vice versa.

Cheers!

Update: OK, thanks for all the info, I've also read in a couple of places that I can't call WaitForSingleObject() if I used _beginthread(), but if I call _endthread() in the thread shouldn't that work? What's the deal there?

C++ Solutions


Solution 1 - C++

CreateThread() is a raw Win32 API call for creating another thread of control at the kernel level.

_beginthread() & _beginthreadex() are C runtime library calls that call CreateThread() behind the scenes. Once CreateThread() has returned, _beginthread/ex() takes care of additional bookkeeping to make the C runtime library usable & consistent in the new thread.

In C++ you should almost certainly use _beginthreadex() unless you won't be linking to the C runtime library at all (aka MSVCRT*.dll/.lib).

Solution 2 - C++

There are several differences between _beginthread() and _beginthreadex(). _beginthreadex() was made to act more like CreateThread() (in both parameters and how it behaves).

As Drew Hall mentions, if you're using the C/C++ runtime, you must use _beginthread()/_beginthreadex() instead of CreateThread() so that the runtime has a chance to perform it's own thread initialization (setting up thread local storage, etc.).

In practice, this means that CreateThread() should pretty much never be used directly by your code.

The MSDN documents for _beginthread()/_beginthreadex() have quite a bit of detail on the differences - one of the more important is that since the thread handle for a thread created by _beginthread() gets closed automatically by the CRT when the thread exits, "if the thread generated by _beginthread exits quickly, the handle returned to the caller of _beginthread might be invalid or, worse, point to another thread".

Here is what the comments for _beginthreadex() in the CRT source have to say:

Differences between _beginthread/_endthread and the "ex" versions:

1)  _beginthreadex takes the 3 extra parameters to CreateThread
  which are lacking in _beginthread():
    A) security descriptor for the new thread
    B) initial thread state (running/asleep)
    C) pointer to return ID of newly created thread

2)  The routine passed to _beginthread() must be __cdecl and has
  no return code, but the routine passed to _beginthreadex()
  must be __stdcall and returns a thread exit code.  _endthread
  likewise takes no parameter and calls ExitThread() with a
  parameter of zero, but _endthreadex() takes a parameter as
  thread exit code.

3)  _endthread implicitly closes the handle to the thread, but
  _endthreadex does not!

4)  _beginthread returns -1 for failure, _beginthreadex returns
  0 for failure (just like CreateThread).

Update Jan 2013:

The CRT for VS 2012 has an additional bit of initialization performed in _beginthreadex(): if the process is a "packaged app" (if something useful is returned from GetCurrentPackageId()) the runtime will initialize the MTA on the newly created thread.

Solution 3 - C++

In general, the correct thing to do is to call _beginthread()/_endthread() (or the ex() variants). However, if you use the CRT as a .dll, the CRT state will be properly initialized and destroyed as the CRT's DllMain will be called with DLL_THREAD_ATTACH and DLL_THREAD_DETACH when calling CreateThread() and ExitThread() or returning, respectively.

The DllMain code for the CRT can be found in the install directory for VS under VC\crt\src\crtlib.c.

Solution 4 - C++

This is the code at the core of _beginthreadex (see crt\src\threadex.c):

    /*
     * Create the new thread using the parameters supplied by the caller.
     */
    if ( (thdl = (uintptr_t)
          CreateThread( (LPSECURITY_ATTRIBUTES)security,
                        stacksize,
                        _threadstartex,
                        (LPVOID)ptd,
                        createflag,
                        (LPDWORD)thrdaddr))
         == (uintptr_t)0 )
    {
            err = GetLastError();
            goto error_return;
    }

The rest of _beginthreadex initializes per-thread data structure for CRT.

The advantage of using _beginthread* is that your CRT calls from thread will work correctly.

Solution 5 - C++

You should use _beginthread or _beginthreadex to allow the C runtime library to do it's own initialization of the thread. Only C/C++ programmers need to know this as they should now the rules of using their own development environment.

If you use _beginthread you do not need to call CloseHandle as the RTL will do for you. This is why you cannot wait on the handle if you have used _beginthread. Also _beginthread leads to confusion if the thread function exits immediately (quickly) as the launching thread my be left holding an invalid thread handle to the thread it just launched.

_beginthreadex handles can be used for wait but also require an explicit call to CloseHandle. This is part of what makes them safe for using with wait. There other issue to make it completely foolproof is to always start the thread suspended. Check for success, record handle etc. The resume thread. This is required to prevent a thread from terminating before the launching thread can record its handle.

Best practice is to use _beginthreadex, start suspended then resume after recording handle, wait on handle is OK, CloseHandle must be called.

Solution 6 - C++

CreateThread() used to have memory leaks when you use any CRT functions in your code. _beginthreadex() has same parameters as CreateThread() and it's more versatile than _beginthread(). So I recommend you use _beginthreadex().

Solution 7 - C++

Regarding your updated question: "I've also read in a couple of places that I can't call WaitForSingleObject() if I used _beginthread(), but if I call _endthread() in the thread shouldn't that work?"

In general, you can pass a thread handle to WaitForSingleObject() (or other APIs that wait on object handles) to block until the thread has completed. But the thread handle created by _beginthread() is closed when _endthread() is called (which can be done explicitly or is done implicitly by the run time when the thread procedure returns).

The problem is called out in the documentation for WaitForSingleObject():

> If this handle is closed while the wait is still pending, the function's behavior is undefined.

Solution 8 - C++

Looking at the function signatures, CreateThread is almost identical to _beginthreadex.

_beginthread, _beginthreadx vs CreateThread

HANDLE WINAPI CreateThread(
  __in_opt   LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in       SIZE_T dwStackSize,
  __in       LPTHREAD_START_ROUTINE lpStartAddress,
  __in_opt   LPVOID lpParameter,
  __in       DWORD dwCreationFlags,
  __out_opt  LPDWORD lpThreadId
);

uintptr_t _beginthread( 
   void( *start_address )( void * ),
   unsigned stack_size,
   void *arglist 
);

uintptr_t _beginthreadex( 
   void *security,
   unsigned stack_size,
   unsigned ( *start_address )( void * ),
   void *arglist,
   unsigned initflag,
   unsigned *thrdaddr 
);

The remarks on here say _beginthread can use either __cdecl or __clrcall calling convention as start point, and _beginthreadex can use either __stdcall or __clrcall for start point.

I think any comments people made on memory leaks in CreateThread are over a decade old and should probably be ignored.

Interestingly, both _beginthread* functions actually call CreateThread under the hood, in C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src on my machine.

// From ~line 180 of beginthreadex.c
/*
 * Create the new thread using the parameters supplied by the caller.
 */
if ( (thdl = (uintptr_t)
      CreateThread( (LPSECURITY_ATTRIBUTES)security,
                    stacksize,
                    _threadstartex,
                    (LPVOID)ptd,
                    createflag,
                    (LPDWORD)thrdaddr))
         == (uintptr_t)0 )
{
        err = GetLastError();
        goto error_return;
}

Solution 9 - C++

beginthreadex gives you a thread HANDLE for use in WaitForSingleObject and friends. beginthread doesn't. Don't forget to CloseHandle() when you are done. The real answer would be to use boost::thread or soon C++09's thread class.

Solution 10 - C++

Compared to _beginthread, with _beginthreadex you can:

  1. Specify security attributes.
  2. Start a thread in suspended state.
  3. You can get the thread id which can be used with OpenThread.
  4. The thread handle returned is guaranteed to be valid if the call was successful. There for you need to close the handle with CloseHandle.
  5. The thread handle returned can be used with synchronization APIs.

The _beginthreadex closely resembles CreateThread, but the former is a CRT implementation and the latter a Windows API call. The documentation for CreateThread contains the following recommendation: > A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multi-threaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.

Solution 11 - C++

CreateThread() is Windows API call that is language neutral. It just creates OS object - thread and returns HANDLE to this thread. All windows applications are using this call to create threads. All languages avoids direct API call for obvious reasons:

  1. You don't want your code be OS specific
  2. You need to do some house keeping before calling API-like: convert parameters and results, allocate temporary storage etc.

_beginthreadex() is C wrapper around CreateThread() that accounts for C specific. It enables original single threaded C f-ns work in multithreaded environment by allocating thread specific storage.

If you don't use CRT you cannot avoid a direct call to CreateThread(). If you use CRT, you must use _beginthreadex() or some CRT string f-ns may not work properly prior VC2005.

Solution 12 - C++

CreateThread() once was a no-no because the CRT would be incorrectly initialize/clean up. But this is now history: One can now (using VS2010 and probably a few versions back) call CreateThread() without breaking the CRT.

[Here is the official MS confirmation][1]. It states one exception:

> Actually, the only function that should not be used in a thread created with CreateThread() is the signal() function.

However, from consistence point of view, I personally prefer to keep using _beginthreadex(). [1]: http://support.microsoft.com/kb/104641/en-us

Solution 13 - C++

CreateThread() is the straight system call. It's implemented on Kernel32.dll which, most probably, your application will already be linked against for other reasons. It is always available in modern Windows systems.

_beginthread() and _beginthreadex() are wrapper functions in the Microsoft C Runtime (msvcrt.dll). The differences between the two calls are stated in the documentation. It is thus available when the Microsoft C Runtime is available, or if your application is linked statically against it. You'll likely be linking against that library, too, unless you're coding in pure Windows API (as I personally often do).

Your question is a coherent and actually a recurrent one. As many APIs, there are duplicate and ambiguous functionality in the Windows API we have to deal with. Worst of all, the documentation does not clarify the issue. I suppose that the _beginthread() family of functions was created for better integration with other standard C functionalities, such as the manipulation of errno. _beginthread() thus integrates better with the C runtime.

Despite that, unless you have good reasons for using _beginthread() or _beginthreadex(), you should use CreateThread(), mostly because you might get one less library dependency in your final executable (and for MS CRT this does matter a bit). You also have no wrapping code around the call, although this effect is negligible. In other words, I believe that the main reason for sticking with CreateThread() is that there is no good reason to use _beginthreadex() to begin with. The functionalities are precisely, or almost, the same.

One good reason to use _beginthread() would be (as it seems to be false) that C++ objects would be properly unwinded/destroyed if _endthread() was called.

Solution 14 - C++

If you read the book Debugging Windows Application From Jeffrey Richter in it he explains that almost in all instances you must call _beginthreadex instead of calling CreateThread. _beginthread is just a simplified wrapper around _beginthreadex.

_beginthreadex initializes certain CRT (C RunTime) internals that the CreateThread API would not do.

A consequence if you use the CreateThread API instead of using _begingthreadex calls to CRT functions might unexpected cause issues.

Check out this old Microsoft Journal From Richter.

Solution 15 - C++

The other answers fail to discuss the implications of calling a C run-time function that wraps a Win32 API function. This is important when considering DLL loader locking behavior.

Whether or not _beginthread{ex} does any special C Runtime thread/fiber memory management as the other answers discuss, it is implemented in (assuming dynamic linking to the C run-time) a DLL that processes may not have loaded yet.

It is not safe to call _beginthread* from DllMain. I have tested this by writing a DLL loaded using the Windows "AppInit_DLLs" feature. Calling _beginthreadex (...) instead of CreateThread (...) causes a LOT of important parts of Windows to stop functioning during bootup as the DllMain entry-point deadlocks waiting for the loader lock to be released in order to perform certain initialization tasks.

Incidentally, this is also why kernel32.dll has a lot of overlapping string functions that the C run-time also does -- use those from DllMain to avoid the same sort of situation.

Solution 16 - C++

You should try this code

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<process.h>

UINT __stdcall Staff(PVOID lp){
 printf("The Number is %d\n", GetCurrentThreadId());
 return 0;
}

INT main(INT argc, PCHAR argv[])
{

    const INT Staff_Number = 5;
    HANDLE hd[Staff_Number];
    for(INT i=0; i < Staff_Number; i++){
       hd[i] = (HANDLE)_beginthreadex(NULL, 0, Staff, NULL, 0, NULL);
    }

 WaitForMultipleObjects(Staff_Number, Staff, TRUE, NULL);
 for(INT i=0; i < Staff_Number; i++)
 {
     CloseHandle(hd[i]);
 }
 system("pause");
 return 0;
}

if you use _beginthread instead of _beginthreadex it will give error too many argument for _beginthread it is because _beginthread couldnt create a thread with security attribute and also i think _beginthread is unnecessary you can absolutely use *(_beginthreadex) and CreateThread

Solution 17 - C++

There is no difference anymore between the both.

All comments about memory leaks etc are based on very old < VS2005 versions. I've done some stress testing years ago and could debunk this myth. Even Microsoft mixes the styles in their examples, almost never using _beginthread.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKirilView Question on Stackoverflow
Solution 1 - C++Drew HallView Answer on Stackoverflow
Solution 2 - C++Michael BurrView Answer on Stackoverflow
Solution 3 - C++MSNView Answer on Stackoverflow
Solution 4 - C++ConstantinView Answer on Stackoverflow
Solution 5 - C++jarcher7View Answer on Stackoverflow
Solution 6 - C++JaywalkerView Answer on Stackoverflow
Solution 7 - C++Michael BurrView Answer on Stackoverflow
Solution 8 - C++boboboboView Answer on Stackoverflow
Solution 9 - C++Gert-JanView Answer on Stackoverflow
Solution 10 - C++VishalView Answer on Stackoverflow
Solution 11 - C++SKVView Answer on Stackoverflow
Solution 12 - C++Serge WautierView Answer on Stackoverflow
Solution 13 - C++alecovView Answer on Stackoverflow
Solution 14 - C++Ehsan SamaniView Answer on Stackoverflow
Solution 15 - C++Andon M. ColemanView Answer on Stackoverflow
Solution 16 - C++testhahaView Answer on Stackoverflow
Solution 17 - C++LotharView Answer on Stackoverflow