본문 바로가기

Windows/MFC

main thread 와 child thread 사이에 공유되는 이벤트 핸들

#include <window.h>
#include <stdio.h>
#include <process.h>

// main thread 와 child thread 사이에 공유되는 이벤트 핸들
// 을 저장하기 위한 전역 변수
HANDLE g_hAutoResetEvent = NULL;
HANDLE g_hManualResetEvent = NULL;

unsigned __stdcall ThreadStartFunc(void* lpThreadParameterId)
{
    DWORD dwStatus;

    // 스레드 시작을 알린다.
    printf("Thread #%d id=0x%08x, started.\n",
        (int) lpThreadParameterId,
        GetCurrentThreadId());

    // auto reset event 대기
    printf("Thread #%d id=0x%08x, waiting for auto-reset event.\n",
        (int) lpThreadParameterId,
        GetCurrentThreadId());

    dwStatus = WaitForSingleObject(g_hAutoResetEvent, INFINITE);

    if (dwStatus == WAIT_OBJECT_0)
    {
        printf("Thread #%d id=0x%08x, wait for auto-reset event succeeded.\n",
            (int) lpThreadParameterId,
            GetCurrentTrheadId());
    }
    else
    {
        printf("Thread #%d id=0x%08x, wait for auto-reset event failed.\n",
            (int) lpThreadParameterId,
            GetCurrentThreadId());

        return 1;
    }

    printf("Thread #%d id=0x%08x, waiting for manual-reset event. \n",
        (int) lpThreadParameterId,
        GetCurrentThreadId());

    dwStatus = WaitForSingleObject(g_hManualResetEvent, INFINITE);

    if (dwStatus == WAIT_OBJECT_0)
    {
        printf("Thread #%d id=0x%08x, wait for manual-reset event succeeded.\n",
            (int) lpThreadParameterId,
            GetCurrentThreadId());
    }
    else
    {
        printf("Thread #%d id=0x%08x, wait for auto-reset event failed.\n",
            (int) lpThreadParameterId,
            GetCurrentThreadId());

        return 2;
    }

    // 종료한다.
    printf("Thread #%d id=0x%08x, exiting. \n",
            (int) lpThreadParameterId,
            GetCurrentThreadId());

    return 0;
}

int main(void)
{
    DWORD dwStatus;
    BOOL bStatus;
    HANDLE ahThreads[2];
    DWORD dwThreadID1;
    DWORD dwThreadID2;

    // 자동 리셋 이벤트를 생성한다.
    g_hAutoResetEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (g_hAutoResetEvent)
    {
        printf("Primary thread created auto-reset event.\n");
    }
    else
    {
        printf("Primary thread unable to create auto-reset event.\n");
        exit(-1);
    }

    // 수동 리셋 이벤트를 생성한다.
    g_hManualResetEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (g_hAutoResetEvent)
    {
        printf("Primary thread created manual-reset event.\n");
    }
    else
    {
        printf("Primary thread unable to craete manual-reset event.\n");
        exit(-2);
    }

    // 첫째 자식 스레드 생성
    ahThreads[0] = (HANDLE) _beginthreadex(NULL, 0, ThreadStartFunc, (void*)1, 0, (unsigned*)&dwThreadID1);
    if (ahThread[0])
    {
        printf("Primary thread created child thread #1 with id=0x%08x.\n", dwThreadID1);
    }
    else
    {
        printf("Primary thread unable to create child thread #1.\n");
        exit(-3);
    }

    // 둘째 자식 스레드를 생성
    ahThreads[1] = (HANDLE) _beginthreadex(NULL, 0, ThreadStartFunc, (void*)2, 0, (unsigned*)&dwThreadID2);
    if (ahThread[1])
    {
        printf("Primary thread created child thread #2 with id=0x%08x.\n", dwThreadID2);
    }
    else
    {
        printf("Primary thread unable to create child thread #2.\n");
        exit(-4);
    }

    // 이벤트를 시그널하기 전에 자식 스레드가 수행을 시작하도록 한다.
    // 프로그램이 제대로 동작하는 데에는 전혀 상관이 없지만, 이렇게 코드를
    // 구성함으로써 둘째 스레드에게 자동 리셋 이벤트를 처음으로 시그널링할
    // 수 있는 동일한 기회를 줄 수 있다.
    Sleep(1000);

    // 자동 리셋 이벤트를 시그널한다.
    printf("Primary thread signaling auto-reset event. \n");
    bStatus = SetEvent(g_hAutoResetEvent);

    if (!bStatus)
    {
        printf("Unable to signal auto-reset event.\n");
        exit(-5);
    }

    // 수동 리셋 이벤트를 시그널링
    printf("Primary thread signaling manual-reset event.\n");
    bStatus = SetEvent(g_hManualResetEvent);

    if (!bStatus)
    {
        printf("Unable to signal manual-reset event.\n");
        exit(-6);
    }
    else

    // 자식 스레드 하나가 종료할 때까지 대기한다.
    printf("Primary thread waiting for one of thre chlid threads to exit. \n");
    dwStatus = WaitForMultipleObjects(2, ahThreads, FALSE, INFINITE);
    if ((dwStatus == WAIT_OBJECT_S) || (dwStatus == WAIT_OBJECT_0 + 1))
    {
        printf("Wait for one child thread to exit succeded.\n");
    }
    else
    {
        printf("Wait for one child thread to exit failed.\n");
        exit(-7);
    }

    // 자동 리셋 이벤트를 다시 시그널링 한다.
    printf("Primary thread signaling auto-reset event again\n");
    bStatus = SetEvent(g_hAutoResetEvent);
    if (!bStatus)
    {
        printf("Unable to signal auto-reset event again\n");
        exit(-8);
    }

    // 스레드 두 개가 모두 종료될 때까지 대기
    printf("Primary thread waiting for both child threads to exit.\n");
    dwStatus = WaitForMultipleObjects(2, ahThreads, TRUE, INFINITE);
    if (dwStatus == WAIT_OBJECT_0)
    {
        printf("Wait for both child threads to exit succeded. \n");
    }
    else
    {
        printf("Wait for both child threads to exit failed.\n");
        exit(-9);
    }

    // 정리 작업
    CloseHandle(ahThread[0]);
    CloseHandle(ahThread[1]);
    CloseHandle(g_hAutoResetEvent);
    CloseHandle(g_hManualResetEvent);

    // 종료
    printf("Primary thread exiting. \n");

    return 0;
}

[code]result
Primary thread created auto-reset event.
Primary thread created manual-reset event.
Primary thread created child thread #1 with id=0xfffabeeb.
Primary thread created child thread #2 with id=0xfffab883.
Thread #1 id=0xfffabeeb, started.
Thread #1 id=0xfffabeeb, waiting for auto-reset event.
Thread #2 id=0xfffab883, started.
Thread #2 id=0xfffab883, waiting for auto-reset event.
Primary thread signaling auto-reset event.
Primary thread signaling manual-reset event.
Primary thread waiting for one of thre chlid threads to exit.
Thread #1 id=0xfffabeeb, waiting for auto-reset event succeeded.
Thread #1 id=0xfffabeeb, waiting for manual-reset event succeeded.
Thread #1 id=0xfffabeeb, exiting.
Wait for one child thread to exit succeeded.
Primary thread signaling auto-reset event succeeded.
Primary thread waiting for both child threads to exit.
Thread #2 id=0xfffab883, waiting for auto-reset event succeeded.
Thread #2 id=0xfffab883, waiting for manual-reset event succeeded.
Thread #2 id=0xfffab883, waiting for auto-reset event succeeded.
Thread #2 id=0xfffab883, exiting.
Wait for both child threads to exit succeeded. Primary thread exiting.
[/code]