티스토리 뷰

Visual Studio 2012 사용


이벤트를 사용해보자.

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


1. 함수원형 살펴보기


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

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 상태로 변환한다.

BOOL SetEvent(
  HANDLE hEvent 
); 

파라미터:

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


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

BOOL ResetEvent( 
  HANDLE hEvent 
); 

파라미터:

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


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

DWORD WaitForSingleObject( 
  HANDLE hHandle, 
  DWORD dwMilliseconds 
); 

파라미터:

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

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


2. 선언


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


ThreadTestDlg.h

// 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

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 상태로 만들어 테스트해보자.




댓글