PostThreadMessage()를 이용한 쓰레드에 메세지 전송

● 알아두어야 할 사항
1. 윈도우 OS시스템에서는 자동적으로(GetMessage()호출시?) 메세지 큐를 각각 쓰레드마다 생성한다.
2. Posted Message를 위한 메세지 큐의 크기는 Windows 2000이나 XP인경우
   10000이다. (최소 값: 4000) 이 값은 아래 윈도우즈 레지스트리에
   HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Windows/
     USERPostMessageLimit
   정의 한다.
3. PostThreadMessage()로 보내어지는 메세지는 윈도우와 관련이 없다.


● 결론
1. 간단한 메세지만 전송받아 처리 하는 쓰레드인 경우는 큐만든다고 삽질하지 말자.
2. 기본에 충실하자.
3. 옛날에 삽질한게 억울하다.

// --------------------------------------------------------------------------
//  예제
// --------------------------------------------------------------------------
CAppModule _Module;

DWORD WINAPI BackgroundThread (LPVOID param)
{
 MSG msg;

 while (GetMessage(&msg, NULL, 0, 0))
 {
  ATLTRACE (_T("hwnd    = %x \r\n"),    msg.hwnd    );
  ATLTRACE (_T("message = %x \r\n"),    msg.message );
  ATLTRACE (_T("wParam  = %x \r\n"),    msg.wParam  );
  ATLTRACE (_T("lParam  = %x \r\n"),    msg.lParam  );
  ATLTRACE (_T("time    = %d \r\n"),    msg.time    );
  ATLTRACE (_T("pt      = %d %d \r\n"), msg.pt.x, msg.pt.y);
  ATLTRACE (_T("\r\n"));

  Sleep (1000);

  while (::PeekMessage (&msg, NULL, WM_USER, WM_USER+5, PM_REMOVE));
 }

 ATLTRACE (_T("BackgroundThread(): End \r\n"));

 return msg.wParam;
}

int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWNORMAL)
{
 CMessageLoop theLoop;
 _Module.AddMessageLoop(&theLoop);

 CMainFrame wndMain;

 DWORD  dwThreadId  = 0;
 HANDLE hThread     = CreateThread (NULL, 0, BackgroundThread, NULL, 0, &dwThreadId);
 wndMain.m_ThreadId = dwThreadId;

 if(wndMain.CreateEx() == NULL)
 {
  ATLTRACE(_T("Main window creation failed!\n"));
  return 0;
 }
 
 wndMain.ShowWindow(nCmdShow);

 int nRet = theLoop.Run();

 _Module.RemoveMessageLoop();

 WaitForSingleObject (hThread, INFINITE);
 CloseHandle (hThread);

 return nRet;
}
// --------------------------------------------------------------------------

LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
 ...
 SetTimer (1, 10);

 return 0;
}

LRESULT CMainFrame::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
 bHandled = FALSE;
 KillTimer (1);
 PostThreadMessage (m_ThreadId, WM_QUIT, 0, 0);

 return 0;
}

LRESULT CMainFrame::OnTimer (UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
 static int i = 0;

 PostThreadMessage (m_ThreadId, WM_USER+(++i%5), 1, 2);

 return 0;
}
// --------------------------------------------------------------------------
// 출력결과
// --------------------------------------------------------------------------
hwnd    = 0
message = 403
wParam  = 1
lParam  = 2
time    = 73702525
pt      = 0 0

hwnd    = 0
message = 400
wParam  = 1
lParam  = 2
time    = 73703559
pt      = 0 0

hwnd    = 0
message = 400
wParam  = 1
lParam  = 2
time    = 73704571
pt      = 0 0

hwnd    = 0
message = 403
wParam  = 1
lParam  = 2
time    = 73705596
pt      = 0 0

hwnd    = 0
message = 403
wParam  = 1
lParam  = 2
time    = 73706642
pt      = 0 0

hwnd    = 0
message = 400
wParam  = 1
lParam  = 2
time    = 73707702
pt      = 0 0

hwnd    = 0
message = 403
wParam  = 1
lParam  = 2
time    = 73708749
pt      = 0 0

hwnd    = 0
message = 400
wParam  = 1
lParam  = 2
time    = 73709776
pt      = 0 0

CMessageLoop::Run - exiting
BackgroundThread(): End
'BackgroundThread' (0x8706cf42) 스레드가 0 (0x0) 코드에서 끝났습니다.
모듈 언로드: commctrl.dll
모듈 언로드: oleaut32.dll
모듈 언로드: ole32.dll
모듈 언로드: rpcrt4.dll
모듈 언로드: lpcrt.dll
'[6702ec62] Test.exe' 프로그램이 1 (0x1) 코드에서 끝났습니다.

 

 

Posted by 셈말짓기 :