Есть несколько различий между _beginthread()
и _beginthreadex()
. _beginthreadex()
был сделан, чтобы действовать больше как CreateThread()
(по обоим параметрам и как он себя ведет).
Как упоминает Дрю Холл , если вы используете среду выполнения C / C ++, вы должны использовать _beginthread()
/ _beginthreadex()
вместо, CreateThread()
чтобы среда выполнения имела возможность выполнить инициализацию собственного потока (настройка локального хранилища потока и т. Д.).
На практике это означает, что это CreateThread()
практически никогда не должно использоваться напрямую в вашем коде.
В документах MSDN для _beginthread()
/ _beginthreadex()
есть довольно много деталей о различиях - одним из наиболее важных является то, что, поскольку дескриптор потока для потока, созданного с помощью, _beginthread()
автоматически закрывается CRT, когда поток завершается, "если поток, созданный _beginthread, завершается быстро дескриптор, возвращаемый вызывающей стороне _beginthread, может оказаться недопустимым или, что еще хуже, указывать на другой поток ".
Вот что _beginthreadex()
говорят комментарии к источнику CRT:
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).
Обновление в январе 2013 г .:
CRT для VS 2012 имеет дополнительный бит инициализации, выполняемый в _beginthreadex()
: если процесс является «упакованным приложением» (если из него возвращается что-то полезное GetCurrentPackageId()
), среда выполнения инициализирует MTA во вновь созданном потоке.