天天看點

PostThreadMessage用法

函數功能:該函數将一個消息放入 (寄送)到指定線程的消息隊列裡,不等待線程處理消息就傳回。

函數原型:BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM IParam);

參數

idThread:其消息将被寄送的線程的 線程辨別符。如果線程沒有消息隊列,此函數将失敗。當線程第一次調用一個Win 32 USER或GDI函數時,系統建立線程的消息隊列。要得到更多的資訊,參見備注。

Msg:指定将被寄送的消息的類型。

wParam:指定附加的消息特定資訊。

IParam:指定附加的消息特定資訊。

傳回值:如果函數調用成功,傳回非零值。如 果函數調用失敗,傳回值是零。若想獲得更多的錯誤資訊,請調用GetLastError函數。如果idThread不是一個有效的線程辨別符或由 idThread确定的線程沒有消息隊

列,GetLastError傳回 ERROR_INVALID_THREAD。

備注:消息将寄送到的線程必須建立消息隊 列,否則調用PostThreadMessage會失敗。用下列方法之一來處理這種情況:

調用PostThreadMessage。 如果失敗,調用Sleep,再調用PostThreadMessage,反複執行,直到PostThreadMessage成功。

建立一個事件對象,再建立線程。在調用 PostThreadMessage之前,用函數WaitForSingleObject來等特事件被設定為被告知狀态。消息将寄送到的線程調用 PeekMessage(£msg,NULL,WM_USER,WM_USER,PM_NOREMOVE)來強制系統建立消息隊列。設定事件,表示線程已 準備好接收寄送的消息。

消息将寄送到的線程通過調用 GetMesssge或PeekMesssge來取得消息。傳回的MSG結構中的hwnd成員為NULL。

速查:Windows NT:3.1及以上版本;Windows:95及以上版本;Windows CE:1.0及以上版本:頭檔案:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環境下以Unicode和ANSI方式實作。

---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------

把window線程間傳送消息仔細的看了一遍,覺得以前的了解 很不深刻。說一說對PostThreadMessage的 了解。

PostThreadMessage是一個線程體發送一個消息 到指定的線程ID,其 原型如下:

BOOL PostThreadMessage(                
                       DWORD idThread,      
                       UINT Msg,         
                       WPARAM wParam,          
                       LPARAM lParam      
);      

       這個函數既可以發送消息給工 作線程,也可以發送給UI線 程。接受PostThreadMessage的 線程必須已經有了一個message queue, 否則調用PostThreadMessage會 失敗。因為此原因使用GetLastError會 得到錯誤碼為1444, 這種情況經常出現,解決方法有如下兩種:

1.         調 用PostThreadMessage, 如果失敗,就Sleep一 段時間再次調用PostThreadMessage直 到調用成功;

2.         創 建一個Event對 象,讓PostThreadMessage等 待接受的線程建立一個message queue。 可以通過調用PeekMessage強 制系統建立一個message queue。 示例代碼如下:

假設mainAPP是發送線程ThreadA是接受線程

/*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是接受線程

/* 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;      
                                    }      
                       }      
             }      
}      

PostThreadMessage傳遞的消息如果要包含信 息,要注意在結束的時候釋放消息中的資訊。在消息中附加資訊方法如下

/*構造資訊如下*/      
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      
/*解釋資訊如下*/      
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;      
               }      
}      

做了一個簡單的消息通信實驗,讓主 線程中等待使用者輸入,産生不同的消息,并把這些消息post給 子線程,子線程根據産生的消息做出不同的反映。這些子線程可以是工作線程也可以是UI線程。

#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

PostThreadMessage用法

\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;

}

要把SETTING 改為多線程的 

Project->Settings->click C/C tab, 

在Category 中選Code Generation, 然後在Use run-time libray 中選一個 

Multithread 配置

繼續閱讀