Windows threading: _beginthread vs _beginthreadex vs CreateThread C++


Question

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?

1
129
5/9/2017 3:02:14 AM

Accepted Answer

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).

94
8/23/2010 9:01:27 PM

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.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon