今回は、イベントについてします。
イベントオブジェクトはシグナル状態とノンシグナル状態のいずれかの状態にあります。WaitForSingleObject関数で待機することができます。シグナル状態になると制御を返します。
イベントオブジェクトを作るにはCreateEvent関数を使います。
HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, // セキュリティ記述子 BOOL bManualReset, // リセットのタイプ BOOL bInitialState, // 初期状態 LPCTSTR lpName // イベントオブジェクトの名前 );lpEventAttributesには、 SECURITY_ATTRIBUTES 構造体へのポインタを指定します。 不要であればNULLを指定します。
bManualReset には、手動リセットオブジェクトを作る場合はTRUE,自動リセットオブジェクトを作る場合はFALSEにします。自動の場合、待機スレッドが解放されると自動的にノンシグナル状態になります。
bInitialStateには、初期状態を指定します。
TRUEでシグナル、FALSEでノンシグナル状態となります。
lpNameには、イベントオブジェクトの名前を指定します。名前無しオブジェクトにするにはNULLを指定します。
関数が成功すると、イベントハンドルが返ります。失敗するとNULLが返されます。
イベントオブジェクトをシグナル状態にするにはSetEvent関数を使います。
BOOL SetEvent( HANDLE hEvent // イベントオブジェクトのハンドル );イベントオブジェクトをノンシグナル状態にするにはResetObject関数を使います。
BOOL ResetEvent( HANDLE hEvent // イベントオブジェクトのハンドル );では、サンプルを見てみましょう。
/* mult06.c */
#include <stdio.h>
#include <windows.h>
#include <process.h>
unsigned __stdcall mythread0(void *);
unsigned __stdcall mythread1(void *);
HANDLE hEvent[3];
int main()
{
    int i;
    HANDLE hTh[2];
    DWORD thID[2];
    hTh[0] = (HANDLE)_beginthreadex(
        NULL,
        0,
        mythread0,
        NULL,
        CREATE_SUSPENDED,
        &thID[0]
    );
    if (hTh[0] == NULL) {
        printf("スレッド0作成失敗\n");
        return -1;
    }
    hTh[1] = (HANDLE)_beginthreadex(
        NULL,
        0,
        mythread1,
        NULL,
        CREATE_SUSPENDED,
        &thID[1]
    );
    if (hTh[1] == NULL) {
        printf("スレッド1作成失敗\n");
        return -1;
    }
    
    hEvent[0] = CreateEvent(NULL, TRUE, FALSE, "CH0");
    hEvent[1] = CreateEvent(NULL, TRUE, FALSE, "CH1");
    hEvent[2] = CreateEvent(NULL, TRUE, FALSE, "MAINEVENT");
    //各スレッド実行開始
    for (i = 0; i < 2; i++)
        ResumeThread(hTh[i]);
    printf("イベント0をシグナル状態にします\n");
    SetEvent(hEvent[0]);
    WaitForSingleObject(hEvent[2], INFINITE);
    printf("親を終了します\n");
    for (i = 0; i < 2; i++)
        CloseHandle(hTh[i]);
    return 0;
}
3つの手動イベントオブジェクトを作っておきます。初期状態はいずれもノンシグナル状態です。
そして、最初のhEvent[0]をシグナル状態にします。
これで、スレッド0が動き出します。
unsigned __stdcall mythread0(LPVOID lpx)
{
    int i;
    WaitForSingleObject(hEvent[0], INFINITE);
    for (i = 0; i < 10; i++)
        printf("子スレッド0[%d]\n", i);
    printf("イベント1をシグナル状態にします\n");
    SetEvent(hEvent[1]);
    return 0;
}
hEvent[0]がシグナル状態になると画面表示を行います。全部表示したら、hEbvent[1]をシグナル状態にします。
unsigned __stdcall mythread1(LPVOID lpx)
{
    int i;
    WaitForSingleObject(hEvent[1], INFINITE);
    for (i = 0; i < 10; i++)
        printf("子スレッド1[%d]\n", i);
    printf("イベント2をシグナル状態にします\n");
    SetEvent(hEvent[2]);
    return 0;
}
hEvent[1]がシグナル状態になったら、画面表示を行います。全部表示したら、hEvent[2]をシグナル状態にします。
これで、main関数の待機状態が終わり、プログラム本体が終了します。
では、実行結果を見てみましょう。
Update Nov/29/2004 By Y.Kumei