• PostThreadMessage


    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\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 配置
  • 相关阅读:
    做到就得到,人生成功的启示
    这个世界没什么过不去的事情,记我的经历
    要想富,先读书,没有文化要吃一辈子的亏
    git学习笔记11-git多人协作-实际多人怎么开发
    git学习笔记10-新开发的功能不想要了-强行删除分支
    git学习笔记09-bug分支-自己的分支改到一半了-要去改bug怎么办?
    git学习笔记08-分支管理策略-实际上我们应该怎么应用分支
    git学习笔记07-冲突了怎么办-那就解决冲突呗
    git学习笔记06-创建分支合并分支-比svn快多了,因为只有指针在改变
    git学习笔记05-从远程库克隆
  • 原文地址:https://www.cnblogs.com/ahuo/p/864948.html
Copyright © 2020-2023  润新知