CreateEvent イベントオブジェクトの作成

Cの宣言:

HANDLE CreateEvent(
	LPSECURITY_ATTRIBUTES Security,
	BOOL ManualReset,
	BOOL InitialState,
	LPCTSTR EventName);

説明:

イベントオブジェクトを生成する。EventNameで指定された名前のイベントオブジェクトが既に存在する場合、そのイベントオブジェクトのハンドルを返す。

イベントオブジェクトには、手動リセットと自動リセットの二つの型がある。自動リセットのイベントオブジェクトは、待機関数がWAIT_OBJECT_0などを返した場合非シグナル状態になる。手動リセットのイベントオブジェクトは、待機関数が終了してもシグナル状態とならない。

イベントオブジェクトの状態を変更するには、SetEventResetEventPulseEventなどの関数を用いる。

非同期I/O処理を行う入出力関数の中には、イベントオブジェクトによって処理終了を通知することのできる関数が存在する。このような例については、後述のサンプルコードを参照。

イベントオブジェクトを参照しているハンドルが全てクローズされると、イベントオブジェクトは自動的に破棄される。

引数の意味は、以下の通り。
Security イベントオブジェクトのセキュリティ属性を指すポインタ。NULLの場合、デフォルトのセキュリティ属性が使用される。
ManualReset TRUEの場合、手動リセットのイベントオブジェクトが作成される。FALSEの場合、自動リセットのイベントオブジェクトが作成される。
InitialState イベントオブジェクトが初期状態でシグナル状態か否かを表す真偽値。
EventName 作成するイベントオブジェクトの名前。NULLを指定した場合、名前無しイベントオブジェクトが作成される。

関数の実行が正常に終了した場合、イベントオブジェクトのハンドルが返される。イベントオブジェクトが新規に作成された場合、GetLastError関数の戻り値は0となる。EventNameによって指定されるイベントオブジェクトが既に存在していた場合、GetLastError関数の戻り値はERROR_ALREADY_EXISTSとなる。関数の実行に失敗した場合、NULLが返される。

自動リセットのイベントオブジェクトの例(C言語):

#define EVENT_NAME "Event Object Test"

/* スレッド用関数
 * “処理”の部分が、排他的な処理となる
 * ThreadCount: 何番目のスレッドか
 */
DWORD WINAPI DoThread(DWORD ThreadCount)
{
	HANDLE hEvent;
	int i;

	hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME);

	for(i=0; i<3; i++) {
		/* 所有権獲得まで待機 */
		WaitForSingleObject(hEvent, INFINITE);

		/* 処理 */
		printf("スレッド%d: 処理開始\n", ThreadCount);
		Sleep(3000);
		printf("スレッド%d: 処理終了\n", ThreadCount);

		/* 開放 */
		SetEvent(hEvent);
	}
	
	CloseHandle(hEvent);
	return(0);
}

/* メイン関数 */
int main(int argc, char **argv)
{
	HANDLE hThread[2];
	HANDLE hEvent;
	int i;

	hEvent = CreateEvent(NULL, FALSE, TRUE, EVENT_NAME);

	/* スレッドを2つ作成 */
	for(i=0; i<2; i++) {
		hThread[i] = CreateThread(
			NULL, 0, (LPTHREAD_START_ROUTINE)DoThread,
			(LPVOID)i, 0, NULL);
		Sleep(1000);
	}

	/* スレッドの終了まで待機 */
	WaitForMultipleObjects(2, hThread, TRUE, INFINITE);

	/* 後処理 */
	CloseHandle(hEvent);
	CloseHandle(hThread[0]);
	CloseHandle(hThread[1]);

	return(0);
}

手動リセットのイベントオブジェクトの例(C言語):

イベントオブジェクトがシグナルになるまで待機するスレッドを複数作成後、イベントオブジェクトをシグナル状態にすることによって、複数のスレッドを同時に実行する。
#include <windows.h>
#include <stdio.h>

#define EVENT_NAME "Event Object Test"

/* スレッド用関数 */
DWORD WINAPI DoThread(DWORD ThreadCount)
{
	HANDLE hEvent;

	hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME);

	/* 所有権獲得まで待機 */
	WaitForSingleObject(hEvent, INFINITE);

	/* 処理 */
	printf("スレッド%d: 処理開始\n", ThreadCount);
	Sleep(3000);
	printf("スレッド%d: 処理終了\n", ThreadCount);
	
	CloseHandle(hEvent);
	return(0);
}

/* メイン関数 */
int main(int argc, char **argv)
{
	HANDLE hThread[2];
	HANDLE hEvent;
	int i;

	hEvent = CreateEvent(NULL, TRUE, FALSE, EVENT_NAME);

	/* スレッドを2つ作成 */
	for(i=0; i<2; i++) {
		hThread[i] = CreateThread(
			NULL, 0, (LPTHREAD_START_ROUTINE)DoThread,
			(LPVOID)i, 0, NULL);
	}

	Sleep(1000);

	/* スレッドの同時実行 */
	printf("スレッド実行\n");
	SetEvent(hEvent);

	/* スレッドの終了まで待機 */
	WaitForMultipleObjects(2, hThread, TRUE, INFINITE);

	/* 後処理 */
	CloseHandle(hEvent);
	CloseHandle(hThread[0]);
	CloseHandle(hThread[1]);

	return(0);
}

非同期I/Oにイベントオブジェクトを使用した例(C言語):

WriteFile関数をオーバーラップ操作で実行することにより、ファイルに対して同時に5つの非同期書き込みを行う。WriteFile関数のOVERLAPPED構造体にイベントオブジェクトを指定することにより、すべての書込み操作の終了を検出する。すべての書込み操作が終了するまでの間、カウントを続ける。
#define BUFMAX 10000000
#define ASYNCNUM 5

void DoAsyncWrite()
{
	HANDLE hEvent[ASYNCNUM];
	OVERLAPPED ov[ASYNCNUM];
	DWORD cbWritten[ASYNCNUM];
	HANDLE hFile;
	char *buf;
	int i, cnt;
	DWORD result;

	/* 書き込むデータの用意 */
	buf = GlobalAlloc(GMEM_FIXED, BUFMAX);
	if(buf == NULL) {
		printf("memory error\n");
		return;
	}
	/* for(i=0; i<BUFMAX; i++) buf[i] = i%256; */

	/* 新規ファイルの作成 */
	hFile = CreateFile(
		"test.dat",
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		CREATE_ALWAYS,
		FILE_ATTRIBUTE_ARCHIVE | FILE_FLAG_OVERLAPPED | FILE_FLAG_WRITE_THROUGH,
		NULL);

	/* イベントオブジェクトの作成とオーバーラップ構造体の初期化 */
	for(i=0; i<ASYNCNUM; i++) {
		hEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);

		ov[i].Offset = 0;
		ov[i].OffsetHigh = 0;
		ov[i].hEvent = hEvent[i];
	}

	/* 非同期書き込みの実行 */
	for(i=0; i<ASYNCNUM; i++) {
		printf("書き込み開始: %d\n", i);
		WriteFile(hFile, buf, BUFMAX, &cbWritten[i], &ov[i]);
	}

	/* 書き込み終了までカウントを続ける */
	for(cnt = 0;;cnt++) {
		printf("Count: %d\n", cnt);
		result = WaitForMultipleObjects(ASYNCNUM, hEvent, TRUE, 1000);
		if(result != WAIT_TIMEOUT) break;
	}

	printf("書き込み終了\n");

	/* 後処理 */
	for(i=0; i<ASYNCNUM; i++) CloseHandle(hEvent[i]);
	
	CloseHandle(hFile);
	GlobalFree(buf);
}

(original text:1998/12/25 更新)

本ドキュメントの内容は保証しません。本ドキュメントによって生じた結果について、一切の責任を負いません。