이벤트란 어떤 사건이 일어났음을 알리는 동기화 객체이다?

 

-       크리티컬섹션, 뮤텍스, 세마포어는 주로 공유자원을 보호하기 위해 사용되는 데 비해 이벤트는 그보다는 스레드간의 작업 순서나 시기를 조정하고 신호를 보내기 위해 사용한다.

 

 

이벤트는 윈도우의 메시지와 유사하다?

 

-       사용자가 키보드 누를 때 WM_KETDOWN 메시지를 윈도우 프로시저에게 보내 처리하게 하는 것처럼 정렬이나 다운로드가 끝났을 때 이벤트를 보내 관련된 다른 작업을 하도록 지시할 수 있다.

 

 

자동 리셋 이벤트

대기 상태가 종료되면 자동으로 비신호상태가 된다.

수동 리셋 이벤트

스레드가 비신호상태로 만들 때까지 신호상태를 유지한다.

 

 

이벤트 함수정리

 

이벤트생성함수

 

HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL blnitialState, LPCTSTR lpname);

 

lpEventAttributes

보안속성

bManualReset

TRUE이면 수동 리셋 이벤트 FALSE이면 자동 리셋 이벤트

blnitialState

TRUE이면 이벤트를 생성함과 동시에 신호상태로 만든다.

lpname

이름

세마포어와 마찬가지로 첫번째, 네번째인자는 프로세스동기화와 관련있다.

 

 

n  이벤트가 뮤텍스나 크리티컬섹션과 또 다른 점은 대기 함수를 사용하지 않고도 임의적으로 신호상태나 비신호상태를 설정할 수 있다는 점이다. 이때 쓰는 함수가 아래와 같다.

 

신호상태변경함수

 

BOOL SetEvent(HANDLE hEvent)

BOOL ResetEvent(HANDLE hEvent)

 

SetEvent

신호상태로 만든다.

ResetEvent

비신호상태로 만든다.

이런 상태변화가 대기중인 스레드에게는 일종의 신호로 전달된다.

 

 

 

자동 리셋 이벤트

 

       대기 상태를 풀 때 자동으로 이벤트를 비신호상태로 만든다는 뜻이다.

       여러 개의 스레드가 하나의 이벤트를 기다리고있을때 적합하지않다.

 

 

수동 리셋 이벤트

 

       대기 상태를 풀 때 신호 상태를 그대로 유지하고 ReSerEvent 함수로 일부러 비신호상태로 만들 때만 상태가 변경된다.

        여러 개의 스레드가 하나의 이벤트를 기다리고있을때 적합하다.



함수 사용 예제

 

HANDLE hEvent;

DWORD WINAPI ThreadSend(LPVOID temp)

{

             WaitForSingleObject(hEvent,INFINITE); //신호상태가 될때까지 무한정대기

             HDC hdc=GetDC(hWndMain);

             TextOut(hdc,210,100,"전송완료",8);

             ReleaseDC(hWndMain, hdc);

             return 0;

}

 

DWORD WINAPI ThreadSave(LPVOID temp)

{

             WaitForSingleObject(hEvent,INFINITE); //신호상태가 될때까지 무한정대기

             HDC hdc=GetDC(hWndMain);

             TextOut(hdc,110,100,"저장완료",8);

             ReleaseDC(hWndMain, hdc);

             return 0;

}

 

DWORD WINAPI ThreadCalc(LPVOID temp)

{

             HDC hdc=GetDC(hWndMain);

             for (int i=0;i<10;i++) {

                           TextOut(hdc,10,50,"계산중",6);

                           GdiFlush();

                           Sleep(300);

                           TextOut(hdc,10,50,"기다려",6);

                           GdiFlush();

                           Sleep(300);

             }

             TextOut(hdc,10,50,"계산완료",8);

             ReleaseDC(hWndMain, hdc);

             SetEvent(hEvent);   //신호상태로 바꿔줌

             return 0;

}

 

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

             HDC hdc;

             PAINTSTRUCT ps;

             DWORD ThreadID;

             TCHAR *Mes="마우스 왼쪽 버튼을 누르면 계산을 시작합니다";

 

             switch (iMessage) {

             case WM_CREATE:

                           hWndMain=hWnd;

                           hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);  //수동이벤트

                          

                           //hEvent=CreateEvent(NULL,FALSE,FALSE,NULL); // 자동 이벤트

                           return 0;

             case WM_LBUTTONDOWN:

                           InvalidateRect(hWnd,NULL,TRUE);

                           ResetEvent(hEvent);

                           CloseHandle(CreateThread(NULL, 0, ThreadCalc, NULL, 0, &ThreadID));

                           CloseHandle(CreateThread(NULL, 0, ThreadSave, NULL, 0, &ThreadID));

                           CloseHandle(CreateThread(NULL, 0, ThreadSend, NULL, 0, &ThreadID));

                           return 0;

             case WM_PAINT:

                           hdc=BeginPaint(hWnd, &ps);

                           TextOut(hdc,10,10,Mes,lstrlen(Mes));

                           EndPaint(hWnd, &ps);

                           return 0;

             case WM_DESTROY:

                           CloseHandle(hEvent);

                           PostQuitMessage(0);

                           return 0;

             }

             return(DefWindowProc(hWnd,iMessage,wParam,lParam));

 

WM_CREATE에서 이벤트 객체를 생성하는데 이 때 두 번째 인수로 TRUE를 지정하여 수동 리셋 이벤트가 되도록하였다.

 

가장 위 에 있는 계산스레드가 실행이되는데 계산이 완료되면 SetEvent함수를 호출하여 신호상태로 만든다.

신호상태로 바뀌어지면 대기하고있던 스레드들이 모두 실행 할 수 있다.

 

, 자동리셋은 같은 상황에서 계산스레드가 끝나고 다른 스레드가 실행되는데 그 스레드가 대기함수를 거치면서 신호를 비신호상태로 바꿔놓음으로서 다른 스레드들은 또 대기를 해야한다.



출처 - 윈도우즈 API 정복 , 한빛미디어

'API & MFC > API & 시스템프로그래밍' 카테고리의 다른 글

스레드의 함정  (0) 2010.01.25
스레드  (0) 2010.01.24
세마포어  (0) 2010.01.24
파일매핑 사용순서  (0) 2010.01.24
Dll이란?  (0) 2010.01.24
Posted by 아몰라