CWinThread 消息映射

Posted

技术标签:

【中文标题】CWinThread 消息映射【英文标题】:CWinThread message maps 【发布时间】:2015-02-10 11:37:52 【问题描述】:

所以我正在深入研究 MFC 的世界,特别是定制使用 CWinThread 来实现工作线程。我已经通过其他方式成功实现了工作线程,因此将 CWinThread 用于工作线程的主要动机是利用消息映射。

为了将来的使用,我将 CWinThread 派生为最终将成为某种形式的超类。请参阅以下声明。

class WinThreadBase : public CWinThread

    DECLARE_DYNCREATE(WinThreadBase)

protected:
    WinThreadBase();           // protected constructor used by dynamic creation
    DECLARE_MESSAGE_MAP()

public:

     BOOL isdone_;
;

这是由以下扩展和实现的

声明

class WinThreadImplementation :public WinThreadBase 
    DECLARE_DYNCREATE(WinThreadImplementation)

protected:
    WinThreadImplementation(); //Declare protected because of dynamic creation

public: 

//The following CWinThread methods have to be overriden to complete specfic work.

    virtual BOOL InitInstance();
    virtual int Run();

private:

    CDialog* owner_;
    BOOL isinit_;

public:
    virtual ~WinThreadImplementation();
    void SetOwner( CDialog* pOwner )  owner_ = pOwner; 
    BOOL Isinit() const  return isinit_; 
    DECLARE_MESSAGE_MAP()

//Message handler declaration
    void OnMyThreadMessage( WPARAM wParam, LPARAM lParam );
    void OnQuit( WPARAM wParam, LPARAM lParam );

;

实现

IMPLEMENT_DYNCREATE( WinThreadImplementation, WinThreadBase)

WinThreadImplementation::WinThreadImplementation() 
    owner_ = FALSE;
    isinit_ = FALSE;



WinThreadImplementation::~WinThreadImplementation() 
    //........Do some stuff here... //


BOOL WinThreadImplementation::InitInstance() 
    //Do some initialisation here..
    return TRUE; //returning true allows thread start successfully


int WinThreadImplementation::Run() 
    isinit_ = TRUE;
    while( !isdone_ ) 
        //Do some work...
        //TRACE( "Hello from pat's derived CWinThread" );
        Sleep( 1000 ); //Give other threads a chance to run..
    

    owner_->PostMessage( WM_QUIT, 0, 0 ); // Tell our parent thread that this thread has finished work                                                                                 
    return 0;


BEGIN_MESSAGE_MAP(WinThreadImplementation,CWinThread)
    //Map messages to handler method here...
    //CWinThread messages must be handles like this....
    ON_THREAD_MESSAGE(WM_MYTHREADMESSAGE,OnMyThreadMessage)
END_MESSAGE_MAP()

//Put message handlers here...`
void WinThreadImplementation::OnMyThreadMessage( WPARAM wParam, LPARAM lParam )       
    TRACE( "Hello from my message handler\n\r" );

现在开始实际发布消息

mywinthreadimpl_ = (WinThreadImplementation*)
        AfxBeginThread( RUNTIME_CLASS( WinThreadImplementation ),     THREAD_PRIORITY_NORMAL,
        0, CREATE_SUSPENDED );
    mywinthreadimpl_->SetOwner( this );
    mywinthreadimpl_->ResumeThread();

    while( !mywinthreadimpl_->Isinit() ); //Make sure that the thread has initialised before attempting to post a message

    if( PostThreadMessage( mywinthreadimpl_->m_nThreadID,   WM_MYTHREADMESSAGE, NULL, NULL ) ) 
        TRACE( "message was sent correctly\n" );
    

所以结果是它编译了,我的 CWinThread 派生正在工作并进入覆盖的运行函数。但我终生无法收到 PostThreadMessage 发布的消息。

我已阅读以下内容

http://support.microsoft.com/kb/142415?wa=wsignin1.0

并得出结论,这不适用于我,因为我使用的是 VS 2010。

谁能建议我可能错过了什么,这会阻止我的 CWinThread 实现接收消息?

谢谢

【问题讨论】:

【参考方案1】:

如果不使用 AfxPumpMessage 或调用 CWinThread 的基类实现 (__super::Run),您将永远不会收到消息!

不要使用 isdone_。而是使用 PostQuitMessage 来终止当前的工作线程。只需使用 Run 的基本实现来运行线程并泵送消息。

您也可以使用 OnIdle 或 CWinThread 的其他功能,来做一些工作...

只是调用 Sleep 会阻塞您的线程,但该线程不会被 Windows 消息中断

【讨论】:

所以如果我希望让这个工作线程处于循环工作状态,就无法接收消息? 或者我可以在进入我的override of run时调用基类Run,然后继续循环工作? 您可以在 OnIdle 中工作...(正如我已经写过的),或者您可以不时使用 PeekMesage / AfxPumpMessage 来检查是否有消息在等待。 我会将其标记为答案。一个小例子会特别有用,但你确实帮助我重新定义了我的搜索,以便我可以找到我需要的所有细节。我想向您提出另一个问题 xMRi,因为我注意到您已经发布了许多 MFC 相关问题的解决方案。所以我的解决方案涉及我在工作循环中使用 AfxPumpMessage() 。当要关闭线程时,跳出循环并执行 ::PostQuitMessage( int )。线程干净利落地退出,所有对象都被销毁了,但是我的父线程怎么知道worker线程已经不存在了 发送消息。设置一个标志。设置一个事件!

以上是关于CWinThread 消息映射的主要内容,如果未能解决你的问题,请参考以下文章

消息映射 MFC:继承多个消息映射

027.MFC_映射消息

wxWidgets源码分析 - 消息映射表

消息映射机制的介绍

MFC如何给菜单添加消息映射

猎豹MFC--消息映射