What\'s a better way to start a thread, _beginthread
, _beginthreadx
or CreateThread
?
I\'m trying to determine what are the adv
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;
}
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. It states one exception:
Actually, the only function that should not be used in a thread created with
CreateThread()
is thesignal()
function.
However, from consistence point of view, I personally prefer to keep using _beginthreadex()
.
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.
#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
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.
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).