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
:
MSG msg;
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:
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.
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:
DWORD m_idThread;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:
PostThreadMessage(m_idThread,WM_APP+1,0,0);
And instructing thread to quit:
PostThreadMessage(m_idThread,WM_QUIT,0,0);
Here is how the running application looks like:
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