Win32でのマルチスレッドのテスト

解説

VC++.netではマルチスレッドのプログラムを作る時は、前準備が必要です。
ソリューションエクスプローラでソリューションの名前を右クリックして「プロパティ」を選択します。
C++」の「コード生成」でランタイムライブラリを「マルチスレッド(/MT)」にします。

#include <stdio.h>
#include <windows.h>

DWORD WINAPI mythread(LPVOID);

int main()
{
	DWORD thID, dwExCode;
	HANDLE hTh;
	int i;

	//スレッドを作成する
	hTh = CreateThread( 
		NULL,
		0,
		mythread,
		NULL,
		0,
		&thID 
	);
    
	if (hTh == NULL) {
		printf("スレッド作成失敗\n");
		return -1;
	}

	for (i = 0; i < 20; i++) {
		printf("Mainです[%d]\n", i);
	}
	// 子スレッドが終了するまで待機
	WaitForSingleObject(hTh, INFINITE);

	if (hTh != NULL) {
		CloseHandle(hTh);
		printf("ハンドルクローズしました\n");
	}

	return 0;
}

DWORD WINAPI mythread(LPVOID lpx)
{
	int i;
	for (i = 0; i < 10; i++)
		printf("スレッドです[%d]\n", i);
	
	printf("子スレッド終了");
	return 0;
}


HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // セキュリティ記述子
DWORD dwStackSize, // 初期のスタックサイズ
LPTHREAD_START_ROUTINE lpStartAddress, // スレッドの機能
LPVOID lpStartAddress, // スレッドの引数
DWORD dwCreationFlags, // 作成オプション
LPDWORD lpThreadId // スレッド識別子
);

lpThreadAttributesには、SECURITY_ATTRIBUTESへのポインタを指定します。 NULLにしてもかまいません。
dwStackSizeには、スレッド関数のスタックサイズを指定します。0にすると呼び出し側と同じになります。

lpStartAddressには、スレッド関数のアドレスを指定します。

lpStartAddressには、スレッド関数に渡す引数を指定します。

dwCreationFlagsには、スレッド関数の初期状態を指定します。
0を指定すると、初期状態からスレッドが動作します。
CREATE_SUSPENDEDを指定すると、スレッドが中断した状態で作られます。
(ResumeThread関数で動作を開始させます)

lpThreadIdには、スレッド識別子へのポインタを指定します。

関数が成功するとスレッドのハンドルが返されます。
失敗するとNULLが返されます。
 
 
 
 
スレッド関数は次のプロトタイプを持ちます。
(もちろん名前は自由に付けてかまいません)

DWORD WINAPI ThreadProc(
LPVOID lpParameter
);
この関数がreturnすると、スレッドは終了します。
 
 
 
 
スレッドの状態を調べるには、GetExitCodeThread関数を使います。

BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode // 終了ステータス
);

hThreadには、スレッドハンドルを指定します。
lpExitCodeには、DWORD型変数へのポインタを指定します。
関数が成功するとこの変数に終了ステータスが格納されます。
まだ実行中の時はSTILL_ACTIVEとなります。
 
 
 
 
DWORD WaitForSingleObject(
HANDLE hHandle, // オブジェクトのハンドル
DWORD dwMilliseconds // タイムアウト時間
);

hHandleには、オブジェクトのハンドルを指定します。
指定できるオブジェクトには、スレッド、イベント、ミューテックスセマフォなどがあります。
dwMillisecondsには、タイムアウト時間を指定します。
これに、INFINITEを指定するとオブジェクトがシグナル状態になるまで待機します。

CreateThread関数はスレッドハンドルを返すので、これを第1引数に指定し、
第2引数をINFINITEにすると、スレッドが終了するまで、この関数は待機します。