Windows スレッド化:_beginthread vs _beginthreadex vs CreateThread C++

CreateThread() カーネル レベルで別の制御スレッドを作成するための生の Win32 API 呼び出しです。

_beginthread() &_beginthreadex() CreateThread() を呼び出す C ランタイム ライブラリ呼び出しです。 舞台裏。一度 CreateThread() 戻ってきました、_beginthread/ex() 新しいスレッドで C ランタイム ライブラリを使用可能にし、一貫性を持たせるために、追加の簿記を処理します。

C++ では、ほぼ確実に _beginthreadex() を使用する必要があります C ランタイム ライブラリ (別名 MSVCRT*.dll/.lib) にまったくリンクしない場合を除きます。


_beginthread() にはいくつかの違いがあります と _beginthreadex() . _beginthreadex() CreateThread() のように振る舞うように作られました (パラメータとその動作の両方で)

Drew Hall が言及しているように、C/C++ ランタイムを使用している場合は、_beginthread() を使用する必要があります。 /_beginthreadex() CreateThread() の代わりに ランタイムが独自のスレッド初期化 (スレッド ローカル ストレージの設定など) を実行できるようにします。

実際には、これは CreateThread() を意味します コードで直接使用することはほとんどありません。

_beginthread() の MSDN ドキュメント /_beginthreadex() 違いについてかなり詳しく説明しています - より重要なことの 1 つは、_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 年 1 月:

VS 2012 の CRT には、_beginthreadex() で実行される追加の初期化ビットがあります。 :プロセスが「パッケージ化されたアプリ」の場合 (GetCurrentPackageId() から何か有用なものが返された場合) ) ランタイムは、新しく作成されたスレッドで MTA を初期化します。


一般に、正しいことは _beginthread()/_endthread() を呼び出すことです (または ex() バリアント)。ただし、CRT を .dll として使用する場合、CRT の状態は適切に初期化され、CRT の DllMain として破棄されます。 DLL_THREAD_ATTACH で呼び出されます と DLL_THREAD_DETACH CreateThread() を呼び出すとき と ExitThread()

DllMain CRT のコードは、VC\crt\src\crtlib.c の下の VS のインストール ディレクトリにあります。