關於PostThreadMessage以及建立線程訊息佇列

來源:互聯網
上載者:User

譯自msdn(節選):http://msdn.microsoft.com/en-us/library/ms644946(v=vs.85).aspx

能接收訊息的線程(即欲向其投遞訊息的線程),必須已經建立了一個訊息佇列,否則調用PostThreadMessage向其發送訊息將失敗。可使用如下方法處理這種情況。

  1. 首先(在源線程中)建立一個事件對象,然後建立新線程

  2. 在(源線程中)調用PostThreadMessage之前,使用WaitForSingleObject函數等待事件直至其被(目標投遞線程)設定為激髮狀態

  3. 在目標投遞線程中,以如下方式調用PeekMessage,從而強制系統為該線程建立訊息佇列:

    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)

  4. 在目標投遞線程中,設定事件為激髮狀態,從而表明其已做好接收投遞訊息的準備

在目標投遞線程中,可通過調用GetMessage或PeekMessage函數取回已投遞的訊息。函數返回的MSG結構中的hwnd成員值為NULL.

由PostThreadMessage發送的訊息沒有與一個視窗(物件控點)相關聯。一般來說,不與一個視窗(物件控點)相關聯的訊息不能被函數DispatchMessage所派發。因此,如果接收者線程處於一個模態迴圈(如使用MessageBox或DialogBox)中時,訊息將會丟失。在此情況下,為攔截線程訊息,可使用線程特定的hook。

 

以下給出一個例子。

轉自:http://www.cppblog.com/sandy/archive/2012/09/20/2320.html

#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;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.