0
votes

So I'm delving into the world of MFC and in particular, customised use of CWinThread to implement worker threads. I have successfully implemented worker threads other ways, so the main motivation for using CWinThread for a worker thread is to make use of the message map.

For future use I am deriving CWinThread into what will eventually become some form of super class.. See the following declaration..

class WinThreadBase : public CWinThread
{
    DECLARE_DYNCREATE(WinThreadBase)

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

public:

     BOOL isdone_;
};

This is extended and implement by the following

The declaration

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 );

};

The implemetation

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" );
}

Now for actually posting the message

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" );
    }

So the result of this is that it compiles, my CWinThread derivation is working and enters the overriden run function. But I cannot for the life of me receive the message posted by PostThreadMessage.

I have read the following

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

and concluded that this does not apply to me since I am using VS 2010.

Can anyone suggest what I may have missed, that would be preventing my CWinThread implementation from receiving the messages?

Thanks

1

1 Answers

1
votes

Without using AfxPumpMessage or calling the base class implementation of CWinThread (__super::Run), you will never receive a message!

Don't use isdone_. Instead use PostQuitMessage to terminate thecurrent workerthread too. Just use the base implementation of Run to run the thread and pump the messages.

You can also use OnIdle or other function of CWinThread, to do some work...

Just calling Sleep blocks your thread but the thread isnever interrupted by a windows message