CAFE

묻고답하기

Re:MsgWaitForMultipleObjects 시간 지연에 대하여...

작성자장성호|작성시간08.11.12|조회수965 목록 댓글 5

설명이 길어질것 같습니다.

간단하게 설명해주고 싶은데, 그럴만큼 실력이 되질 못해요...

 

프로그램은 모두 하나의 process와 한개이상의 thread로 만들어 집니다.

 

시스템에서(윈도우,리눅스..등)에서 대개 여러 프로그램이 동시에 실행시켜놓고 작업할수 잇습니다.

요런걸 멀티 테스킹 이라고 하죠

 

그런데

이론적으로 시스템에 CPU가 하나인경우에 동시에 두개이상의 프로세서가 돌아갈수가 없습니다.

그런데 멀티테스킹이 되는 이유는 사용자가 느끼지 못할 정도의 아주 짧은 시간간격으로

여러프로그램을 조금씩 돌리고 있는것입니다.( os에 따라 틀립니다. , DOS에서는 안되구요..)

 

작업관리자를 띄워보면 현재 시스템에 돌아가는 프로세서가 수십개는되는데

이걸 어떤 순서에 의해 한개씩 시그날시켜줍니다.

이때 cpu 레지스터 정보도 바꿔주고 하는데 이작업을 컨텍스트-스위치 라고 합니다.

앗참 작업은 프로세서가 아니라 쓰레드단위로 돌아갑니다.

 

프로세서는 같은 가상메모리 공간을 가지고 있는 것이고요

실제 코딩이 돌아가는것은 쓰레드이죠

 

프로그램을 만들때 쓰레드 프로그램을 하지 않아도

하나의 프로세서와 하나의 쓰레드로 프로그램은 돌아가게 되죠

 

WaitForSingleObject 하면 넘겨준 객체가 signal 될때까지 현재 쓰레드는 아무 작업을 하지 않습니다.

윈도우 프로그램의 메인쓰레드에서 WaitForSingleObject 를 호출했다면

함수가 끝날때까지 (객체가 signal되거나 , time_out 되거나) 아무작업을 하지 못합니다.

작업관리자에서는 응답없음이 나올것입니다.

 

보통 쓰레드에서 sleep 을 쓰는것보다, 확실하게 쓰레드를 쉬게하려면

WaitForSingleObject , WaitForMultipleObjects 등을 쓰게 됩니다.

 

그런데 윈도우 프로그램(어플리케이션)에서는 메인쓰레드에서

화면에 폼등의 윈도우에 갱신을 해주고 마우스 및 키보드 메세지를 받아서 처리해야 하는 작업을 수시로 해줘야 하기때문에

메인쓰레드에서 WaitForSingleObject , WaitForMultipleObjects 또는 Sleep으로 무한정 대기할수는 없습니다.

메세지를 계속 처리해 줘야죠

 

VCL(C++빌더 또는 델파이)에서는 메세지큐에서 메세지를 가져와(GetMessage 또는 PeekMessage)서

처리해주는 부분이 Application.ProcessMessages; 함수인것입니다.

 

프로젝트 파일을 보면 메인폼을 생성한후에

Application.Run이 있는데

Application.Run안에 따라가보면

Application.ProcessMessages 를 프로그램이 종료될때까지 반복적으로 호출해 줍니다.

 

그런데 Application.ProcessMessages를 계속 반복적으로 호출해주는것보다

메세지가 있을때만 호출해주는게 좋지 않을까요?

 

그래서 나온 함수가 MsgWaitForMultipleObjects 입니다.

이 함수는 넘겨주는 객체(Object)들이 signal 되거나

현재 쓰레드의 메세지큐에 메세지가 들어오면 함수가 return됩니다.

 

메세지가 없을때는 그냥 계속 non-singnal 상태에 들어가게 되는거죠

cpu 자원을 효율적으로 쓰는 방법이할 할수 있습니다.

 

쓰레드에서 Sleep보다 WaitForSingleObject 를 쓰는것도

cpu자원을 효율적으로 쓰는 방법 이라 할수 있구요

 

단 VCL에서는 Application.OnIdle 이벤트 핸들러가 있습니다.

이는 처리해야 할 메세지가 없을때 발생하는 이벤트 입니다.

Peekmessage로 메세지 큐에서 메세지를 가져왔는데

메세지가 없는경우에 OnIdle이벤트가 발생하구요

또  VCL내부적으로 이때 처리하는게 있기도 합니다.

프로그램에 따라 중요할수도 전혀 중요하지 않을수도 있는 부분이구요

 

하여튼

MsgWaitForMultipleObjects  함수에서 return되면

그대 Application.ProcessMessages 를 호출하는것이 훨씬 효율적이라고 할수있습니다.

 

지식이 짧아서 설명이 제대로 못한것 같네요

 

그럼..

 

---------------------------------질문 원문 ---------------------------------------

안녕하세요.

 

프로그램 개발 중에 시간 지연 처리가 필요하여 알아보던 중 MsgWaitForMultipleObjects 이란 함수를 알게 되었습니다.

 

다음과 같이 사용하면 된다고 합니다.

 

procedure WaitForTimer(MilliSeconds: LongInt);
const
  _SECOND = -10000;

var
  lBusy : LongInt;
  hTimer : HWND;
  liDueTime : LARGE_INTEGER;

begin
  hTimer := CreateWaitableTimer(nil, True, 'WaitableTimer');

  if hTimer = 0 then Exit;

  liDueTime.QuadPart := _SECOND * MilliSeconds;
  SetWaitableTimer(hTimer, TLargeInteger(liDueTime), 0, nil, nil, False);

  repeat
    lBusy := MsgWaitForMultipleObjects(1, hTimer, False, INFINITE, QS_ALLINPUT);
    Application.ProcessMessages;
  until lBusy = WAIT_OBJECT_0;

  CloseHandle(hTimer);
end;


그런데 궁금한 것은 시간 지연할 때 다음과 같이 Application.ProcessMessages 를 사용하는 것으로 알고 있었는데

 

procedure WaitApplication(Milliseconds: Longint);
var
  FirstTickCount: LongInt;
begin
  FirstTickCount := GetTickCount;
  repeat
    Application.ProcessMessages;
  until ( (GetTickCount - FirstTickCount) >= Milliseconds );
end;

 

위의 MsgWaitForMultipleObjects 를 사용하는 것과 Application.ProcessMessages 를 사용하는 것은

어떤 경우에 따라 각각 적용해야 좋은 것인지요?

 

아니면 어느 것을 사용해도 시간 지연 처리는 차이가 없는 것인지요?

 

다음과 같이 만들어본 예제에서는 차이가 없던데요...

 

 

 

다운로드:

 

첨부파일 시간지연예제.rar

 

 

다음검색
현재 게시글 추가 기능 열기

댓글

댓글 리스트
  • 작성자윤서재환아빠 | 작성시간 08.11.12 장성호님 긴 장문의 답변 정말 감사합니다...굉장히 깊이 있는 부분까지 설명해 주셨는데 고맙습니다...제가 이해하기로는 위의 시간 지연 함수들 중에서 Application.ProcessMessages 가 들어간 함수로 시간 지연을 처리하는 것 보다 MsgWaitForMultipleObjects 가 들어간 함수로 시간 지연을 처리하는 것이 CPU에 부담을 주지 않는다 라고 생각 됩니다...그런건가요???
  • 작성자장성호 작성자 본인 여부 작성자 | 작성시간 08.11.12 네 맞습니다. MsgWaitForMultipleObjects 는 메세지큐에 메세지가 들어올때까지 현재 쓰레드는 죽어있게 되는것이구요 Application.ProcessMessages는 쓰레드가 살아있으면서 메세지큐에 메세지가 있는지 없는지 반복해서 직접 확인하구 있으면 메세지를 처리하는것이니까 메세지가 있을때는 상관없지만 메세지가 없을때는 while구문도 그렇게 Application.ProcessMessages도 그렇구 쓸데없는 작업이 될 가능성이 크죠
  • 작성자윤서재환아빠 | 작성시간 08.11.13 아 그렇군요...상세한 답변 정말 감사합니다...앞으로는 MsgWaitForMultipleObjects 가 들어간 시간 지연 함수를 사용하는 것이 좋겠군요...^.^
  • 작성자일레븐 | 작성시간 08.11.13 저도 감사합니다 ~.~
  • 작성자수인아빠 | 작성시간 08.11.14 저도 감사요^^
댓글 전체보기
맨위로

카페 검색

카페 검색어 입력폼