Tutorial 16: Event Object
이 번장에서는, 이벤트 오브젝트가 어떤 것인지를 설명하고, multi-thread 프로그램의 사용 방법을 설명한다.
소스 | 리소스 스크립트 | 실행 결과 |
|
이전 장에서 윈도우 메세지를 사용자정의 해서 thread간의 통신방법을 어떻게 처리하는 지를 설명을 했지만, 나머지 2개의 방법(글로벌영역변수를 사용하는 방법과 이벤트 오브젝트를 사용하는 방법)은, 설명하지 않았기 때문에, 이 장에서는 이 2개의 방법을 설명한다.
이벤트 오브젝트는 2가지의 상태만 표현가능하고, 마치 스위치와 같은 구조로 되어 있다. 이벤트 오브젝트 스위치가 ON이 되면, 「Signal」상태로되고, 이벤트 오브젝트 스위치가 OFF가 되면, 「Non Sinal」상태가된다. 이벤트 오브젝트를 생성하면, 해당 이벤트 오브젝트의 상태를 감시할 수 있는 thread에, 감시 프로그램을 작성해야 한다. 만약 이벤트 오브젝트가 Non Signal 상태라면, 이벤트 오브젝트를 기다리는 thread가 대기상태가 된다. thread가 대기 상태일 때, CPU에 부하는 걸리지 않는다.
CreateEvent 함수를 호출하는 것으로, 이벤트 오브젝트를 생성할 수 있다. 이 함수의 프로토타입은다음과 같다.
CreateEvent proto lpEventAttributes : DWORD,\ bManualReset : DWORD,\ bInitialState : DWORD,\ lpName : DWORD
- lpEventAttribute
보안속성의 포인터로서 , NULL이면 기본값으로 설정된다- bManualReset
TRUE면 수동 리셋 오브젝트가, FALSE면 자동 리셋 오브젝트가 생성된다. 수동 리셋 오브젝트는 ResetEvent 함수를 호출해서 이벤트 오브젝트를 Non Signal상태로 만들고 , 자동 리셋 오브젝트는 WaitForSingleObject 함수를 호출한 후 자동으로 Non Signal상태가 된다.- bInitialState
이벤트 오브젝트의 초기 상태를 지정한다. TRUE면 Signal상태로 설정하고, FALSE면 Non Signal 상태로 설정한다.- lpName
이벤트 오브젝트명을 지정한다. OpenEvent 함수를 호출 할 경우 이름을 사용하게 된다.호출이 성공적으로 수행되면 생성된 이벤트 오브젝트의 핸들을 돌려주고, 실패하면, NULL이 설정된다.
이벤트 오브젝트 상태를 변경하는 2개의 API 함수가 있다. SetEvent 함수와 ResetEvent 함수이다. SetEvent 함수는 이벤트 오브젝트를 Signal 상태로 설정하고,ResetEvent 함수는 Non Signal상태로 설정한다.이벤트 오브젝트가 생성되었을 경우, 이벤트 오브젝트 상태를 감시하는 thread로, WaitForSingleObject 함수를 호출 해야만 한다. WaitForSingleObject 함수의 프로토타입은 다음과 같다.
WaitForSingleObject proto hObject:DWORD, dwTimeout:DWORD
- hObject
동기 오브젝트의 핸들. 이벤트 오브젝트는 동기 오브젝트의 일종이다.- dwTimeout
이벤트 오브젝트 상태가 Signal 상태가 될 때까지 대기하는 시간을 밀리세컨드 단위로 지정한다. 만약 지정한 시간내에 Signal상태가 되지 않으면, WaitForSingleObject 함수는 호출한 곳으로 제어를 반환한다. Signal상태가 될 때까지 무한정 대기하고 싶다면, INFINITE를 지정한다.(1000 ms = 1 Second)
|
유저가 「run thread」를 선택하면, thread는 오랜 시간이 걸리는 계산코드를 실행한다. 계산 코드가 종료되면, 처리가 종료되었다는 메시지 박스가 표시된다. thread가 실행하는 동안에, 유저가 thread를 중지시킬 수 있도록, 「stop thread」메뉴를 선택할 수 있다.
|
|
이 예제에서는, 이전 장과는 다른 thread 기술을 사용하고 있다.
.IF uMsg==WM_CREATE invoke CreateEvent, NULL, FALSE, FALSE, NULL mov hEventStart, eax mov eax, OFFSET ThreadProc invoke CreateThread, NULL, NULL, eax, NULL, 0, ADDR ThreadID invoke CloseHandle, eaxWM_CREATE 메세지를 받으면, 초기 상태가 Non Signal상태의 자동 리셋형의 이벤트 오브젝트를 생성한 뒤, thread를 생성한다. 그렇지만, thread는 곧바로 작동하지 않는다.이것은 다음의 코드와 같이, 이벤트 오브젝트가 Signal상태가 되도록 기다리기 때문이다.
ThreadProc PROC USES ecx Param:DWORD invoke WaitForSingleObject, hEventStart, INFINITE mov ecx, 600000000thread 함수의 첫행은 WaitForSingleObject 함수의 호출로서, 이벤트 오브젝트가 Signal상태가 될 때까지 제어를 반환하지 않는다. 즉, thread가 생성되었을 때, thread는 정지상태가 되는 것이다.
유저가 「run thread」메뉴를 선택하면, 다음과 같이 이벤트 오브젝트를 Signal상태로 설정한다.
.if ax==IDM_START_THREAD invoke SetEvent, hEventStartSetEvent 함수의 호출로 인해, 이벤트 오브젝트를 Signal상태로 설정하고,이벤트 오브젝트 상태를 감시하는 thread 프로시저를 호출하는 WaitForSingleObject 함수로 제어가 옮겨지고, thread가 시작되게 된다. 유저가 「stop thread」메뉴를 선택하면, 글로벌 변수「EventStop」를 TRUE로 설정한다.
.if EventStop==FALSE add eax, eax dec ecx .else invoke MessageBox, hwnd, ADDR StopString, ADDR AppName, MB_OK mov EventStop, FALSE jmp ThreadProc .endif위의 코드에는, thread를 종료하고, WaitForSingleObject 함수를 다시 호출 한 곳으로 점프 한다. 여기서 이벤트 오브젝트를 수동으로 Non Signal상태로 설정 할 필요는 없다. 왜냐면, CreateEvent 함수의 인수중 하나인 bManualReset 를 FALSE로 설정했기 때문이다.