After reading the messages sent between windows threads carefully, I feel that my previous understanding is not profound. Talk about the understanding of PostThreadMessage.
PostThreadMessage is a thread body that sends a message to the specified thread ID. Its prototype is as follows:
BOOL PostThreadMessage(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
This function can either send a message to the worker thread or to the UI thread. The thread receiving PostThreadMessage must already have a message queue, otherwise the call to PostThreadMessage will fail. For this reason, using GetLastError will get an error code of 1444. This situation often occurs. There are two solutions:
1. Call PostThreadMessage, if it fails, Sleep will call PostThreadMessage again for a period of time until the call succeeds;
2. Create an Event object, let PostThreadMessage wait for the thread to create a message queue. You can force the system to create a message queue by calling PeekMessage. The sample code is as follows:
Assuming that mainAPP is the sending thread ThreadA is the receiving thread
/*mainAPP.cpp*/
...
hStartEvent = ::CreateEvent(0,FALSE,FALSE,0); //create thread start event
if(hStartEvent == 0)
{
printf("create start event failed,errno:%d/n",::GetLastError());
return 1;
}
::WaitForSingleObject(hStartEvent,INFINITE);
CloseHandle(hStartEvent);
if(!PostThreadMessage(threadaID, WM_MESSAGE_A,0,0))
{
_tprintf(_T("post error! %d/n"), GetLastError());
return 1;
}
...
ThreadA is the accepting thread
/* ThreadA */
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
if(!SetEvent(hStartEvent))
{
printf("set event error,%d/n",GetLastError());
return 1;
}
while(true){
if(GetMessage(&msg, 0,0,0)) {
switch(msg.message){
case WM_MESSAGE_A:
...
break;
}
}
}
}
If the message passed by PostThreadMessage contains information, pay attention to releasing the information in the message at the end. The method of attaching information to the message is as follows
/*The structure information is as follows*/
char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg
sprintf(pInfo,"msg_%d",++count);
PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0)//post thread msg
/*The explanation information is as follows*/
if(GetMessage(&msg,0,0,0)) //get msg from message queue
{
switch(msg.message)
{
case MY_MSG:
char * pInfo = (char *)msg.wParam;
printf("recv %s/n",pInfo);
delete[] pInfo; //Resources are released here
break;
}
}
Do a simple message communication experiment, let the main thread wait for user input, generate different messages, and post these messages to the child threads, and the child threads make different responses according to the generated messages. These child threads can be worker threads or UI threads.
#include <windows.h>
#include <cstdio>
#include <process.h>
#define MY_MSG WM_USER+100
const int MAX_INFO_SIZE = 20;
HANDLE hStartEvent; // thread start event
// thread function
unsigned __stdcall fun(void *param)
{
printf("thread fun start/n");
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
if(!SetEvent(hStartEvent)) //set thread start event
{
printf("set start event failed,errno:%d/n",::GetLastError());
return 1;
}
while(true)
{
if(GetMessage(&msg,0,0,0)) //get msg from message queue
{
switch(msg.message)
{
case MY_MSG:
char * pInfo = (char *)msg.wParam;
printf("recv %s/n",pInfo);
delete[] pInfo;
break;
}
}
};
return 0;
}
int main()
{
HANDLE hThread;
unsigned nThreadID;
hStartEvent = ::CreateEvent(0,FALSE,FALSE,0); //create thread start event
if(hStartEvent == 0)
{
printf("create start event failed,errno:%d/n",::GetLastError());
return 1;
}
//start thread
hThread = (HANDLE)_beginthreadex( NULL, 0, &fun, NULL, 0, &nThreadID );
if(hThread == 0)
{
printf("start thread failed,errno:%d/n",::GetLastError());
CloseHandle(hStartEvent);
return 1;
}
//wait thread start event to avoid PostThreadMessage return errno:1444
::WaitForSingleObject(hStartEvent,INFINITE);
CloseHandle(hStartEvent);
int count = 0;
while(true)
{
char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg
sprintf(pInfo,"msg_%d",++count);
if(!PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0))//post thread msg
{
printf("post message failed,errno:%d/n",::GetLastError());
delete[] pInfo;
}
::Sleep(1000);
}
CloseHandle(hThread);
return 0;
}
To change SETTING to multi-threaded
Project->Settings->click C/C tab,
Choose Code Generation in Category, then choose one in Use run-time libray
Multithread configuration
Transfer from: http://blog.csdn.net/liuliu20036/article/details/3879152