Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VC10.0

PostThreadMessage Demystified

4.63/5 (21 votes)
21 Jun 2013CPOL2 min read 84.8K   3.8K  
How and Where to use it!

Introduction

Demystifying the use of much unused and highly advantageous API available for multi-threading!. Code given here is for learning/demo purpose, SHOULDN'T  BE USED DIRECTLY INTO PRODUCTION.  

Using the Code

For years working in multithread environment, I always wonder what's the use of PostThreadMessage? Could it can be utilized in worker thread (though I used the same in UI thread derived from CWinThread).

I am sure every API provided has something for use, otherwise Microsoft programmers are not stupid to provide something which is not working as part of API library. So I created a test program and when playing with worker thread, I provided a message loop inside it with HWND parameter passed as NULL:

C++
// Window MSG Structure
MSG msg;

// Window blocking Message Loop
while(GetMessage(&msg,0,0,0))
{
	DispatchMessage(&msg);
}

This means that getmessage can gather message for current thread whether it is thread message or window message. Here is the extract from MSDN.

“If hWnd is NULL, GetMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both window messages and thread messages are processed.”

Now I added a message handler inside message loop which would wait for say thread message (WM_APP+1) to perform some action, otherwise it with continue with its work. Our fully loaded thread function would look something like this:

C++
DWORD threadProc(LPVOID lParam)
{
	MSG msg;
	while(GetMessage(&msg,0,0,0))
	{
		if(msg.message == WM_APP+1)
		{
			MessageBoxA(NULL,"Hello","From Thread",MB_OK);
		}
		DispatchMessage(&msg);
	}

	MessageBoxA(NULL,"Thread will closed On pressing OK","From Thread",MB_OK);
	return 0;
}

Now, you are still wondering where our PostThreadMessage API is and how to use it? Now PostThreadMessage API works on thread ID instead of HWND or window handle. Here is a small extract of PostThreadMessage from MSDN:

Posts a message to the message queue of the specified thread. It returns without waiting for the thread to process the message.

C++
BOOL WINAPI PostThreadMessage(
  __in  DWORD idThread,
  __in  UINT Msg,
  __in  WPARAM wParam,
  __in  LPARAM lParam
);

Now, to get the thread id, when creating thread you have to pass DWORD variable by reference to gather the thread id of newly created worker thread, something like this:

C++
DWORD m_idThread;// in Main Class
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadProc,0,0,&m_idThread);

Same in _beginthreadex() API, however there is no such arrangement in _beginthread() API to retrieve thread id. Though there are ways, I am not them discussing here, i.e., off topic. Now that you have the thread id of worker thread, using PostThreadMessage you can post message to thread, i.e., for saying hello:

C++
PostThreadMessage(m_idThread,WM_APP+1,0,0);

And instructing thread to quit:

C++
PostThreadMessage(m_idThread,WM_QUIT,0,0);

Here is how the running application looks like:

posthreadmessage/PostThreadMessage1.JPG

posthreadmessage/posthreadMessage2.JPG

Points of Interest

I was more interested in posting it as a tip and tricks; however I thought that posting it as an article would target a larger audience.

History

  •  21-June-2013 - Updated 
  • 14 July 2011: Posted on CodeProject

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)