_beginthreadNT
process.h:インデックス への移動
ヘッダーファイル
process.h
カテゴリ
プロセス制御ルーチン
プロトタイプ
unsigned long _beginthreadNT(void (_USERENTRY *start_address)(void *), unsigned stack_size, void *arglist, void *security_attrib, unsigned long create_flags, unsigned long *thread_id);
説明
Windows NT で新しいスレッドの実行を開始します。
メモ: start_address は,_USERENTRY として宣言される必要があります。
マルチスレッド Windows NT プログラムでは,オペレーティングシステムのスレッド作成 API 関数のかわりに,_beginthreadNT または _beginthread 関数を使用する必要があります。これは,これらの関数がランタイムライブラリ関数の正しい動作に必要な初期化を実行するからです。_beginthreadNT 関数は,オペレーティングシステムのセキュリティをサポートします。これらの関数は,マルチスレッドライブラリでのみ使用できます。
_beginthreadNT 関数は,新しいスレッドを作成して開始します。スレッドは,start_address の位置で実行を開始します。スレッドが終了すると,_endthread 関数が自動的に呼び出されます。_endthread はスレッドハンドルを閉じ,ExitThread API を呼び出します。
スタックサイズ(バイト単位)は stack_size です。スタックは,このスタックサイズが 4096 の倍数まで切り上げられた後で,オペレーティングシステムによって割り当てられます。スレッド arglist は NULL でもかまいませんが,指定する必要があります。
_beginthreadNT 関数は,security_attr ポインタを使って SECURITY_ATTRIBUTES 構造体にアクセスします。この構造体には,スレッドのセキュリティ属性が含まれます。security_attr が NULL の場合,スレッドは,デフォルトのセキュリティ属性を使って作成されます。security_attr が NULL の場合,スレッドハンドルは継承されません。
_beginthreadNT は,スレッドの作成に関する追加情報を提供するフラグを create_flags 変数から読み取ります。この変数を 0 に設定すると,スレッドは作成後ただちに実行されます。この変数を CREATE_SUSPENDED に設定することもできます。その場合,スレッドは,ResumeThread 関数が呼び出されるまで実行されません。ResumeThread は Win32 API から提供されます。
_beginthreadNT は,thread_id 変数をスレッド識別子で初期化します。
戻り値
成功した場合,_beginthreadNT は,新しいスレッドのハンドルを返します。この戻り値は,オペレーティングシステムの API(SuspendThread,ResumeThread など)で使用できる標準 Windows ハンドルです。
エラーが発生した場合は -1 を返し,グローバル変数 errno に次のいずれかの値が設定されます。
EAGAIN |
スレッドが多すぎる |
EINVAL |
スタックサイズが無効(16 バイト未満,0 であるなど) |
ENOMEM |
メモリが不十分 |
MSDN ライブラリで,Win32 API GetLastError の説明も参照してください。
例
/* この例では,-tWM(32 ビットマルチスレッドターゲット)コマンドラインスイッチを使用します。*/
#pragma checkoption -tWM
#include <windows.h>
#include <process.h>
#include <stdio.h>
#define NTHREADS 25
static LONG runningThreads = 0;
static HANDLE doneEvent;
/* この関数は,新しいスレッドの「main」関数として動作します */
static void threadMain(void *arg)
{
printf("Thread %2d has an ID of %u\n", (int)arg, GetCurrentThreadId());
/* InterlockedDecrement() を使用して,グローバルな runningThreads を
* スレッドセーフな方法で変更します。カウントが 0 になると,イベントを
* 作成したかどうかをメインスレッドに通知します
*/
if (InterlockedDecrement(&runningThreads) == 0 && doneEvent)
SetEvent(doneEvent);
}
int main(void)
{
HANDLE hThreads[NTHREADS];
int i;
DWORD threadId;
SECURITY_ATTRIBUTES sa = {
sizeof(SECURITY_ATTRIBUTES), /* 構造体のサイズ */
0, /* セキュリティ記述子はなし */
TRUE /* スレッドハンドルは継承可能です */
};
/* 最初は一時停止状態で作成され,threadMain() で実行を開始する NTHREADS 個の継承可能スレッドを作成します*/
for(i = 0; i < NTHREADS; i++) {
hThreads[i] = (HANDLE)_beginthreadNT(
threadMain, /* スレッドの開始アドレス */
4096, /* スレッドのスタックサイズ */
(void *)i, /* スレッドの開始引数 */
&sa, /* スレッドのセキュリティ */
CREATE_SUSPENDED, /* 一時停止状態で作成します */
&threadId); /* スレッド ID */
if(hThreads[i] == INVALID_HANDLE_VALUE) {
MessageBox(0, "Thread Creation Failed", "Error", MB_OK);
return 1;
}
++runningThreads;
printf("Created thread %2d with an ID of %u\n", i, threadId);
}
printf("\nPress ENTER to thaw all threads\n\n");
getchar();
/* すべてのスレッドが完了したときに通知するイベントを作成します */
doneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
/* 一時停止状態のスレッドを再開します */
for(i = 0; i < NTHREADS; i++)
ResumeThread(hThreads[i]);
/* 可能であれば,すべてのスレッドが実行を終了するまで待ちます */
if (doneEvent) {
WaitForSingleObject(doneEvent, INFINITE);
CloseHandle(doneEvent);
}
return 0;
}
移植性
POSIX | Win32 | ANSI C | ANSI C++ |
---|---|---|---|
+ |