プラットフォーム SDK
CreateThread
呼び出し側プロセスの仮想アドレス空間で実行するべき 1 個のスレッドを作成します。
他のプロセスの仮想アドレス空間内で動作する 1 個のスレッドを作成するには、CreateRemoteThread 関数を使ってください。
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // セキュリティ記述子
DWORD dwStackSize, // 初期のスタックサイズ
LPTHREAD_START_ROUTINE lpStartAddress, // スレッドの機能
LPVOID lpParameter, // スレッドの引数
DWORD dwCreationFlags, // 作成オプション
LPDWORD lpThreadId // スレッド識別子
);
パラメータ
- lpThreadAttributes
- 1 個の 構造体へのポインタを指定します。この構造体で、子プロセスが、取得したハンドルを継承できるかどうかを指定します。このパラメータで NULL を指定すると、取得したハンドルを継承できません。
Windows NT/2000:SECURITY_ATTRIBUTES 構造体の lpSecurityDescriptor メンバで、新しいスレッドに適用されるセキュリティ記述子を設定します。このパラメータで NULL を指定すると、既定のセキュリティ記述子がこのスレッドに適用されます。
- dwStackSize
- スタックの初期のコミットサイズを、バイト単位で指定します。システムはこの値を、ページサイズの倍数のうち最寄りの値へ丸めます。このパラメータで、0 または既定のコミットサイズより小さい値を指定すると、呼び出し側スレッドのコミットサイズと同じサイズが、既定のサイズとして割り当てられます。詳細については、MSDN ライブラリの「」を参照してください。
- lpStartAddress
- LPTHREAD_START_ROUTINE 型のアプリケーション定義関数へのポインタを指定します。この関数は新しいスレッドで実行されるものであり、同時に新しいスレッドの開始アドレスを指定します。このスレッド関数の詳細については、MSDN ライブラリの ThreadProc を参照してください。
- lpParameter
- スレッドに渡す 1 個のパラメータの値を指定します。
- dwCreationFlags
- スレッド作成に関する制御フラグを指定します。CREATE_SUSPENDED フラグを指定すると、新しいスレッドは中断された状態で作成され、ResumeThread 関数を呼び出すまでは動作しません。このパラメータで 0 を指定すると、作成と同時に新しいスレッドが動作します。現時点では、ほかの値はサポートされていません。
- lpThreadId
- 1 個の変数へのポインタを指定します。関数から制御が返ると、この変数に、スレッド識別子が格納されます。
Windows NT/2000:このパラメータで NULL を指定すると、スレッド識別子は格納されません。
Windows 95/98:このパラメータで NULL を指定することはできません。
戻り値
関数が成功すると、新しいスレッドのハンドルが返ります。
関数が失敗すると、NULL が返ります。拡張エラー情報を取得するには、 関数を使います。
lpStartAddress パラメータがデータ、コード、またはアクセス不可能なアドレスを指している場合であっても、CreateThread 関数が成功する可能性があることに注意してください。無効な開始アドレスを指定してスレッドを動作させると、例外が発生し、そのスレッドは終了します。無効な開始アドレスが原因でスレッドが終了した場合、そのスレッドが所属するプロセスへ制御が返り、エラー処理が行われます。この動作は、非同期で動作する CreateProcess 関数の性質に似ています。CreateProcess は、プロセスが無効または存在しない DLL(ダイナミックリンクライブラリ)を指している場合でも、そのプロセスを作成します。
Windows 95/98:32 ビットプログラムのコンテキスト内で CreateThread 関数を呼び出した場合にのみ、この関数は成功します。16 ビットプログラムが 32 ビット DLL を呼び出した場合、その DLL は追加のスレッドを作成できません。
解説
1 つのプロセスが作成できるスレッドの数は、利用可能な仮想メモリによって制限されます。既定では、各スレッドに 1MB のスタック空間が割り当てられています。そのため、最大 2,028 個のスレッドを作成できます。また、既定のスタックサイズを減らすことにより、さらに多くのスレッドを作成することもできます。しかし、アプリケーションのパフォーマンスを向上させるには、1 個のプロセッサにつき 1 個のスレッドを作成し、アプリケーションがコンテキスト情報を維持するために利用する要求の数に合わせてキューを構築することを推奨します。各スレッドは、1 つのキューの中のすべての要求を処理した後で、次のキューの中の要求を処理します。
新しいスレッドを作成すると、THREAD_ALL_ACCESS アクセス権を割り当てられた新しいスレッドハンドルが作成されます。セキュリティ記述子が提供されていない場合、スレッドオブジェクトのハンドルを必要とする関数は、そのハンドルを利用できます。セキュリティ記述子が提供されている場合、それ以降、そのハンドルを使おうとすると、アクセスを許可する前にアクセスチェックを行います。アクセスチェックの結果、アクセスが拒否された場合、要求側プロセスはスレッドにアクセスする目的でそのハンドルを使うことはできません。スレッドが 1 台のクライアントを偽装している場合、セキュリティ記述子として NULL を指定して CreateThread 関数を呼び出すと、作成されたスレッドオブジェクトに既定のセキュリティ記述子が割り当てられ、偽装トークンの TokenDefaultDacl(GetTokenInformation 構造体の TokenInformation メンバの値)が表す所有者またはメンバだけにアクセスを許可します。詳細については、MSDN ライブラリの「」を参照してください。
この関数が lpStartAddress パラメータで指定したアドレスで、スレッドの動作が開始されます。関数から制御が返ると、戻り値の DWORD を使って ExitThread 関数を暗黙的に呼び出し、そのスレッドを終了させます。スレッドの戻り値を取得するには、GetExitCodeThread 関数を使います。
作成されるスレッドに割り当てられる相対優先順位値は、THREAD_PRIORITY_NORMAL です。スレッドの相対優先順位値の取得または設定を行うには、GetThreadPriority 関数と SetThreadPriority 関数を使います。
スレッドが終了すると、スレッドオブジェクトはシグナル状態になり、そのオブジェクトを待っていたすべてのスレッドの要求が満たされます。
スレッドが終了し、 関数を使って、そのスレッドに関連するすべてのハンドルを閉じるまで、スレッドオブジェクトはシステム内に残ります。
ExitProcess、ExitThread、CreateThread、CreateRemoteThread の各関数、および CreateProcess 関数を呼び出した結果起動されるプロセスは、1 つのプロセス内で互いにシリアル化されます。1 つのアドレス空間内で一度に実施されるのは、これらのイベントのうちただ 1 つです。そのため、次の制約が適用されます。
•プロセスの起動と DLL の初期化を行うルーチンの中で新しいスレッドを作成することは可能ですが、そのプロセスに関係する DLL の初期化が終了するまでは、それらのスレッドは開始されません。
•1 つのプロセスの DLL 初期化ルーチンまたは DLL デタッチルーチンの中に一度に存在できるスレッドは、ただ 1 つです。
•特定のプロセスに対して ExitProcess 関数を実行すると、そのプロセスに関係する DLL 初期化ルーチンまたはデタッチルーチン内にスレッドが存在しなくなるまで、ExitProcess 関数は制御を返しません。
C のランタイムライブラリに記録されている関数を使うスレッドは、CreateThread 関数と ExitThread 関数ではなく、C のランタイム関数である beginthread 関数と endthread 関数を使うべきです。この方法に従わないと、ExitThread 関数を呼び出したときにわずかなメモリリークが発生します。
対応情報
Windows NT/2000:Windows NT 3.1 以降
Windows 95/98:Windows 95 以降
ヘッダー:Winbase.h 内で宣言、Windows.h をインクルード
インポートライブラリ:Kernel32.lib を使用
参照
, CreateProcess, CreateRemoteThread, ExitProcess, ExitThread, GetExitCodeThread, GetThreadPriority, ResumeThread, SetThreadPriority, , ThreadProc