分享

工作线程与消息循环

 水中麒麟 2014-03-03
分类: VC and C++ 1038人阅读 评论(0) 收藏 举报

转载自:http://www./qinqing1984/archive/2009/04/15/80038.html 

首先声明, 这里的工作线程与UI线程是相对的,即没有任何窗口的. 如果需要与主线程或其它辅助线程通讯,有几种方法如事件,消息,信号等,也可以是以上几种方法的综合运用.下面就列出以下3种通讯方法的代码框架

  (1)只用消息通讯

  1. DWORD ThreadProc(LPVOID lParam)  
  2. {  
  3.     //创建线程消息队列   
  4.     MSG msg;  
  5.     PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);  
  6.     //通知其它线程消息队列已创建好   
  7.     SetEvent(hEvent);   
  8.   
  9.     while(true)  
  10.     {  
  11.       GetMessage(&msg, NULL, 0, 0);  
  12.       switch(msg.message)  
  13.        {  
  14.           case WM_QUIT:  
  15.                 return 1;  
  16.   
  17.           //自定义消息1处理   
  18.           case WM_USER + 100:  
  19.                 break;  
  20.   
  21.           //自定义消息2处理   
  22.           case WM_USER + 101:  
  23.                 break;  
  24.        }  
  25.     }  
  26.     return 0;  
  27. }  


(2)只用事件通讯

  1. DWORD ThreadProc(LPVOID lParam)  
  2. {  
  3.       DWORD dwIndex;  
  4.       while (true)  
  5.       {  
  6.           dwIndex = WaitForMultipleObjects(cObjects, pObjects, FALSE, INFINTE);  
  7.           if (WAIT_OBJECT + 0== dwIndex)  
  8.           {  
  9.               return 1;     //假设为退出事件   
  10.             }  
  11.           else if (WAIT_OBJECT + 1 == dwIndex)  
  12.           {  
  13.             //事件1, 处理程序   
  14.            }          
  15.           else if (WAIT_OBJECT + cObjects - 1 == dwIndwx)  
  16.           {  
  17.             //事件2, 处理程序   
  18.            }  
  19.       }  
  20. }  


(3)用消息和事件通讯

 

  1. DWORD ThreadProc(LPVOID lParam)  
  2. {  
  3.    while (TRUE)  
  4.   {  
  5.         DWORD ret ;   
  6.         MSG msg ;   
  7.     
  8.         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))   
  9.         {   
  10.         switch(msg.message)  
  11.          {  
  12.            //线程退出消息,直接返回   
  13.             case WM_QUIT:  
  14.                 return 1;  
  15.   
  16.            //自定义消息1处理   
  17.             case WM_USER + 100:  
  18.                 break;  
  19.             //自定义消息2处理   
  20.            case WM_USER + 101:  
  21.                break;  
  22.          }  
  23.        }  
  24.        ret = MsgWaitForMultipleObjects(cObjects, lphObjects, FALSE,INFINITE,QS_POSTMESSAGE);   
  25.        if (ret == (WAIT_OBJECT_0 + cObjects))  
  26.        {  
  27.           //有新的消息到来,继续到上步PeekMessage处理   
  28.           continue;  
  29.        }   
  30.        else   
  31.        {   
  32.           //事件处理   
  33.          if (ret == WAIT_OBJECT_O)  
  34.          {                 
  35.          }  
  36.          else if (ret == WAIT_OBJECT_O + 1)  
  37.          {  
  38.          }  
  39.          else if(ret == WAIT_OBJECT_O + cObjects - 1)  
  40.          {  
  41.          }  
  42.       }      
  43.     return 0;  
  44. }  


上面用到了GetMessage和PeekMessage 函数, 这两者都是从消息队列取出消息, 不同的是GetMessage从消息队列删除消息,并且阻塞调用线程. PeekMessage则是查询消息队列,如果有消息就取出,没有消息也立即返回,   是否从消息队列删除消息由最后一个参数决定:PM_REMOVE表示删除,PM_NOREMOVE表示不删除.可以简单地认为,GetMessage是同步的,PeekMessage是异步的

 

*******************************************************************************************************

除以上作者所提到的线程通信方法外还有一种利用MFC消息循环通信的方法,其操作过程如下:

1.从CWnd派生类CSendDataWnd

  1. #define WM_SENDDATA WM_USER+100   
  2. #define WM_POSTDATA WM_USER+101   
  3.   
  4. class CSendDataWnd : public CWnd  
  5. {  
  6. public:  
  7.     CSendDataWnd();  
  8.   
  9. protected:  
  10.     //{{AFX_MSG(CSendDataWnd)   
  11.     LRESULT OnSendData(WPARAM wParam, LPARAM lParam);  
  12.     LRESULT OnPostData(WPARAM wParam, LPARAM lParam);  
  13.     //}}AFX_MSG   
  14.     DECLARE_MESSAGE_MAP()  
  15. };  
  16.   
  17.   
  18. BEGIN_MESSAGE_MAP(CSendDataWnd, CWnd)  
  19.     ON_MESSAGE(WM_SENDDATA, OnSendData)  
  20.     ON_MESSAGE(WM_POSTDATA, OnPostData)  
  21. END_MESSAGE_MAP()  
  22.   
  23. CSendDataWnd::CSendDataWnd() {  
  24.   
  25. }  
  26.   
  27. LRESULT CSendDataWnd::OnSendData(WPARAM wParam, LPARAM lParam)  
  28. {  
  29.     switch(wParam) {  
  30.         //自定义消息处理   
  31.     }  
  32.     return 0;  
  33. }  
  34.   
  35. LRESULT CSendDataWnd::OnPostData( WPARAM wParam, LPARAM lParam )  
  36. {  
  37.     switch(wParam) {  
  38.         //自定义消息处理   
  39.     }  
  40.     return 0;  
  41. }  

2.声明CSendDataWnd变量

  1. CSendDataWnd m_wndSendData;  

 

3.调用CreateEx创建窗口

  1. if (!m_wndSendData.CreateEx(0, AfxRegisterWndClass(0),  
  2.     _T("SendData Notification window"),  
  3.     WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL)) {  
  4.     TRACE("Create SendData Notification window error!\n");  
  5.     AfxThrowResourceException();  
  6. }  


4.向CSendDataWnd窗口发送处理消息

  1. m_wndSendData.SendMessage(WM_SENDDATA, wParam, lParam);  
  2. //或   
  3. m_wndSendData.PostMessage(WM_POSTDATA, wParam, lParam);  


5.使用完毕后,在适当位置调用DestroyWindow销毁消息窗口防止内存泄露

  1. m_wndSendData.DestroyWindow();  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多