HANDLE CreateEvent( LPSECURITY_ATTRIBUTES Security, BOOL ManualReset, BOOL InitialState, LPCTSTR EventName);
イベントオブジェクトには、手動リセットと自動リセットの二つの型がある。自動リセットのイベントオブジェクトは、待機関数がWAIT_OBJECT_0などを返した場合非シグナル状態になる。手動リセットのイベントオブジェクトは、待機関数が終了してもシグナル状態とならない。
イベントオブジェクトの状態を変更するには、SetEvent、ResetEvent、PulseEventなどの関数を用いる。
非同期I/O処理を行う入出力関数の中には、イベントオブジェクトによって処理終了を通知することのできる関数が存在する。このような例については、後述のサンプルコードを参照。
イベントオブジェクトを参照しているハンドルが全てクローズされると、イベントオブジェクトは自動的に破棄される。
引数の意味は、以下の通り。
| Security | イベントオブジェクトのセキュリティ属性を指すポインタ。NULLの場合、デフォルトのセキュリティ属性が使用される。 |
| ManualReset | TRUEの場合、手動リセットのイベントオブジェクトが作成される。FALSEの場合、自動リセットのイベントオブジェクトが作成される。 |
| InitialState | イベントオブジェクトが初期状態でシグナル状態か否かを表す真偽値。 |
| EventName | 作成するイベントオブジェクトの名前。NULLを指定した場合、名前無しイベントオブジェクトが作成される。 |
関数の実行が正常に終了した場合、イベントオブジェクトのハンドルが返される。イベントオブジェクトが新規に作成された場合、GetLastError関数の戻り値は0となる。EventNameによって指定されるイベントオブジェクトが既に存在していた場合、GetLastError関数の戻り値はERROR_ALREADY_EXISTSとなる。関数の実行に失敗した場合、NULLが返される。
#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);
}
#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);
}
#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);
}