PostThreadMessage

PostThreadMessage 向线程发送消息

说明:

函数功能:该函数将一个消息放入(寄送)到指定线程的消息队列里,不等待线程处理消息就返回。

  函数原型:
  

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

参数
  idThread:其消息将被寄送的线程的线程标识符。如果线程没有消息队列,此函数将失败。当线程第一次调用一个Win32 USER或GDI函数时,系统创建线程的消息队列.
  Msg:指定将被寄送的消息的类型。
  wParam:指定附加的消息特定信息。
  IParam:指定附加的消息特定信息。

这个函数既可以发送消息给工作线程,也可以发送给UI线程。
接受PostThreadMessage的线程必须已经有了一个message queue,否则调用PostThreadMessage会失败。
因为此原因使用GetLastError会得到错误码为1444,这种情况经常出现,解决方法有如下两种:
1. 调用PostThreadMessage,如果失败,就Sleep一段时间再次调用PostThreadMessage直到调用成功;
2. 创建一个Event对象,让PostThreadMessage等待接受的线程创建一个message queue。可以通过调用PeekMessage强制系统创建一个message queue。

示例代码如下:
假设mainAPP是发送线程ThreadA是接受线程,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 */
    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;             
        }
    }

参数生命周期

在内存理解上,最著名的例子就是线程启动时的参数传递。
  函数启动一个线程,很多时候需要向线程传参数,但是线程是异步启动的,即很可能启动函数已经退出了,而线程函数都还没有正式开始运行,
因此,绝不能用启动函数的内部变量给线程传参。道理很简单,函数的内部变量在浮动栈,但函数退出时,浮动栈自动拆除,内存空间已经被释放了。
当线程启动时,按照给的参数指针去查询变量,实际上是在读一块无效的内存区域,程序会因此而崩溃。
那怎么办呢?我们应该直接用malloc函数给需要传递的参数分配一块内存区域,将指针传入线程,线程收到后使用,最后线程退出时,free释放。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值