zoukankan      html  css  js  c++  java
  • 关于PostThreadMessage以及创建线程消息队列

    译自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;
    }

  • 相关阅读:
    判断js中的类型
    js数组的4种遍历方式
    js笔记
    Windows 常用 CMD 命令介绍
    css笔记
    winform项目笔记:
    Angular4 中内置指令的基本用法
    Angular4入门笔记
    8、跳台阶
    7、斐波那契数列
  • 原文地址:https://www.cnblogs.com/qinfengxiaoyue/p/3043818.html
Copyright © 2011-2022 走看看