본문 바로가기
Programming/MFC

[MFC] Thread 에서 이벤트를 사용해보자 CreateEvent, SetEvent, ResetEvent

by roomySky 2021. 4. 27.

zadd.tistory.com/57

 

[MFC] 이벤트를 사용해보자 CreateEvent, SetEvent, ResetEvent

Visual Studio 2012 사용 이벤트를 사용해보자. 이벤트는 Event Object를 의미하며, 이 오브젝트를 활용하여 WaitForSingleObject(), WaitForMultipleObjects() 등의 함수에 Signaled, Nonsignaled 상태를 리턴..

zadd.tistory.com

 

 

Visual Studio 2012 사용

 

이벤트를 사용해보자.

이벤트는 Event Object를 의미하며, 이 오브젝트를 활용하여 WaitForSingleObject(), WaitForMultipleObjects() 등의 함수에 Signaled, Nonsignaled 상태를 리턴받아 처리하기위한 목적으로 사용한다. 스레드에서 사용된다.

 

1. 함수원형 살펴보기

 

(1) CreateEvent(): Event Object HANDLE을 생성한다.

1

2

3

4

5

6

HANDLE CreateEvent(

  LPSECURITY_ATTRIBUTES lpEventAttributes,

  BOOL bManualReset,

  BOOL bInitialState,

  LPTSTR lpName

);

파라미터:

IpEventAttributes - 무시, NULL값 입력하면 된다.

bManualReset - TRUE시에는 ResetEvent()을 활용해 Manual로 이벤트를 리셋 시켜야한다. FALSE시는 이벤트가 Signaled 상태가 되면 Single Waiting Thread 이후 자동으로 Nonsignaled 상태로 변한다.

bInitialState - 초기 이벤트 상태를 나타낸다. TRUE시 Signaled, FALSE시 Nonsignaled.

 

IpName - Event Object의 이름을 나타내는 포인터. 보통 NULL값을 사용한다.

 

 

(2) SetEvent(): 해당 Event Object의 상태를 Signaled 상태로 변환한다.

1

2

3

BOOL SetEvent(

  HANDLE hEvent

);

파라미터:

hEvent  - Event Object를 입력하면 된다.

 

(3) ResetEvent(): 해당 Event Object의 상태를 Nonsignaled 상태로 변환한다.

1

2

3

BOOL ResetEvent(

  HANDLE hEvent

);

파라미터:

hEvent  - Event Object를 입력하면 된다.

 

(4) WaitForSingleObject(): 스레드에서 해당 Event Object의 상태를 불러올 때 사용한다. Event말고도 Thread 핸들이나 다른 Object의 상태를 볼 때도 사용된다.

1

2

3

4

DWORD WaitForSingleObject(

  HANDLE hHandle,

  DWORD dwMilliseconds

);

파라미터:

hHandle - Event Object를 입력하면 된다.

dwMilliseconds  - Time Out 관련 변수이다. INFINITE가 입력되면 해당 Event Object가 Signaled가 될 때까지 계속 기다린다. 숫자가 입력되면 해당 숫자의 시간만큼(ms기준) 기다린 후, WAIT_TIMEOUT을 리턴한다.

 

2. 선언

 

테스트를 위해 ThreadTest란 이름의 MFC 대화상자 프로젝트를 생성했다.

 

ThreadTestDlg.h

1

2

3

4

5

6

7

8

9

// CThreadTestDlg 대화 상자

class CThreadTestDlg : public CDialogEx

{

//...

public:

  HANDLE g_hEvent;

  static UINT MyThread(LPVOID lParam);

  CWinThread *m_pThread;

};

 

Event Object를 적용할 HANDLE(g_hEvent)과, 스레드로 활용할 MyThread를 선언하였다.

 

3. 정의

 

ThreadTestDlg.cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

BOOL CThreadTestDlg::OnInitDialog()

{

  //...

 

  g_hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

  m_pThread = AfxBeginThread(MyThread,this);

   

  return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.

}

 

UINT CThreadTestDlg::MyThread(LPVOID lParam)

{

  CThreadTestDlg *g_pDlg = (CThreadTestDlg*)lParam;

  UINT ret;

 

  HANDLE pEvent = (g_pDlg->g_hEvent);

 

  while(TRUE)

  {

    ret = WaitForSingleObject(pEvent,INFINITE);

 

    if(ret==WAIT_FAILED) //HANDLE이 Invalid 할 경우

    {

      return 0;

    }

    else if(ret==WAIT_TIMEOUT) //TIMEOUT시 명령

    {

      continue;

    }

    else

    {

      //Event Object: Signaled 상태

      //프로그램 코드

      ResetEvent(pEvent); //Event Object Nonsignaled 상태로 변환

    }

  }

  return ret;

}

(1) OnInitDialog() 함수에서 EventObject와 스레드를 정의한다.

(2) 스레드에서는 Event Object Handle을 넘겨 받고 WaitForSingleObject()를 활용하여 Event 상태를 받는다.

*여기서는 INFINITE를 사용하여 Signaled 상태를 받을 때까지 대기한다.

(3) Signaled 상태일 시 "//프로그램 코드"를 실행 한후 ResetEvent() 함수로 상태를 Nonsignaled 상태로 변환한다. 이렇게 되면 스레드는 다시 WaitForSingleObject()로 넘어가서 대기한다.

 

4. 테스트

 

버튼 하나 만들어서 SetEvent(g_hEvent); 를 사용하여 Event Object를 Signaled 상태로 만들어 테스트해보자.