• 转载使用PostThreadMessage在Win32线程间传递消息


    PostThreadMessage

    This function places a message in the message queue of the specified thread and then returns without waiting for the thread to process the message.

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

    Parameters

    idThread
    [in] Identifier of the thread to which the message will be posted.
    Msg
    [in] Specifies the type of message to be posted.
    wParam
    [in] Specifies additional message-specific information.
    lParam
    [in] Specifies additional message-specific information.

    Return Values

    Nonzero indicates success. Zero indicates failure. To get extended error
    information, call GetLastError. GetLastError
    returns ERROR_INVALID_THREAD_ID if idThread is not a valid thread
    identifier.


    Remarks

    The thread to which the message is posted retrieves the message by calling
    the GetMessage or PeekMessage function. The hwnd member
    of the returned MSG structure is NULL.

    PostThreadMessage可以用于线程之间的异步通讯,因为它不用等待调用者返回,
    这也许是线程通讯中最简单的一种方法了。

    但是要注意以下问题
    1 .PostThreadMessage有时会失败,报1444错误(Invalid thread identifier. )
    其实这不一定是线程不存在的原因,也有可能是线程不存在消息队列(message queue)造成的。
    事实上,并不是每个thread都有message queue,那如何让thread具有呢?
    答案是,至少调用message相关的function一次,比如GetMessage,PeekMessage。

    2.如果是post动态分配的memory给另外一个thread,要注意内存的正确释放。

    3.PostThreadMessage不能够post WM_COPYDATE之类的同步消息,否则会报错

    4.最好不要使用PostThreadMessage post message给一个窗口,使用PostMessage替代。

    下面是我写的一个比较严整的例子,仅供参考。

    #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;
    }
  • 相关阅读:
    抛开BlazeDS,自定义flex RPC
    设计模式学习03装饰器模式
    通过ANT生成MANIFEST.MF中的ClassPath属性
    Spring JDBCTemplate与Hiberante混用
    关于 两个 datetime 列的差别导致了运行时溢出
    在Wcf中使用Nhibernate (续)
    sql2005/sql2008 分页
    工行支付api查询asp.net C# 实现
    生成静态页面的vbscript
    Asp.net Mvc Post ID Bug
  • 原文地址:https://www.cnblogs.com/kex1n/p/2023504.html
Copyright © 2020-2023  润新知