zoukankan      html  css  js  c++  java
  • 转载使用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;
    }
  • 相关阅读:
    《数据结构》2.2顺序表(sequence list)
    《算法竞赛入门经典》6.3.1二叉树-小球下落
    java_时间戳与Date_相互转化
    java事物
    Mysql如何向存在外键的数据表中插入数据
    git基本配置
    mysql时间属性之时间戳和datetime之间的转换
    【转】变量命名(简短且无歧义)
    【转】mybatis实战教程(mybatis in action),mybatis入门到精通
    [转]DAO层,Service层,Controller层、View层
  • 原文地址:https://www.cnblogs.com/kex1n/p/2023504.html
Copyright © 2011-2022 走看看