How to manage user messege sent by PostThreadMessage
Hi - I have problem with receiving a message sent by PostThreadMessage. I'm posting message from main application class (CWinApp). I'm posting it to my class derived from CWinThread. Part of my thread class code:
CReaderThread.h
Code:
CReaderThread : public CWinThread {
[...]
afx_msg void OnMessageTest( WPARAM, LPARAM );
protected:
DECLARE_MESSAGE_MAP()
[...]
}
in CReaderThread.cpp
Code:
BEGIN_MESSAGE_MAP(CReaderThread, CWinThread)
ON_THREAD_MESSAGE( WM_MESSAGE_TEST, OnMessageTest )
END_MESSAGE_MAP()
BOOL CReaderThread::InitInstance() {
TRACE( _T("CReaderThread::InitInstance() START\r\n") );
if ( reader != NULL ) {
if ( start() == true ) {
mainLoop();
}
}
stop();
TRACE( _T("CReaderThread::InitInstance() STOP\r\n") );
AfxEndThread(0);
return TRUE;
}
void CReaderThread::mainLoop() {
long startTime = 0x00;
long endTime = 0x00;
long time2wait = 0x00;
MSG msg;
while ( CRealtime::getInstance()->isWorking() ) {
startTime = GetTickCount();
if ( PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE) ) {
TRACE( _T("RECEIVED message : %i\r\n"), msg.message);
}
[...]
::WaitForSingleObject( stopEvent->m_hObject, time2wait );
}
}
void CReaderThread::OnMessageTest( WPARAM wP, LPARAM lP ) {
TRACE( _T("Get Message wP=%i, lP=%i\r\n"), wP, lP );
return;
}
BOOL CReaderThread::PreTranslateMessage(MSG* pMsg) {
if ( pMsg->message == WM_MESSAGE_TEST ) {
OnMessageTest( pMsg->wParam, pMsg->lParam );
}
return CWinThread::PreTranslateMessage(pMsg);
}
I set breakpoints after PeekMessage(), in OnMessageTest() and in PreTranslateMessage() - nothing. Messages are lost. How to make my thread to receive sended messages?
Greetings.
AragornX
Re: How to manage user messege sent by PostThreadMessage
AfxEndThread() call looks a bit suspicious. What it's for?
Re: How to manage user messege sent by PostThreadMessage
Also I do not see where you start message loop, where you pump messages.
Re: How to manage user messege sent by PostThreadMessage
about AfxEndThread - http://msdn.microsoft.com/en-us/libr...8VS.80%29.aspx
"Must be called from within the thread to be terminated." - so I used it.
and about message loop - do I need to write it by myself ? I thought that it's implemented in CWinThread. Could you write me a sample of that message loop, and where should I place it ? I need to execute some code in same time intervals - I doing it in my mainLoop()... Thank you for answers...
Re: How to manage user messege sent by PostThreadMessage
About AfxEndThread:
"Call this function to terminate the currently executing thread."
Re: How to manage user messege sent by PostThreadMessage
I do not remember already how to do that in MFC, but in WinAPI one must do something along the lines of:
BOOL rv;
MSG msg = {};
while (0 != (rv = GetMessage(&msg, 0, 0, 0)))
{
if (-1 == rv)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Re: How to manage user messege sent by PostThreadMessage
but doesn't it block my main loop ?
Re: How to manage user messege sent by PostThreadMessage
Quote:
Originally Posted by
dvyukov
AfxEndThread() call looks a bit suspicious. What it's for?
I agree. It is wrong to call AfxEndThread() here. Just return TRUE from InitInstance() is enough and correct.
Quote:
Originally Posted by
dvyukov
Also I do not see where you start message loop, where you pump messages.
It is started within CWinThread class (CWinThread::Run method).
So there is no need to explicitely call GetMessage nor TranslateMessage/DispatchMessage
Re: How to manage user messege sent by PostThreadMessage
Here is code that works:
class CReaderThread : public CWinThread
{
afx_msg void OnMessageTest( WPARAM, LPARAM )
{
AfxMessageBox(L"MESSAGE ARRIVED");
}
virtual BOOL InitInstance( )
{
return 1;
}
protected:
DECLARE_MESSAGE_MAP()
};
class Ctest7445App : public CWinApp
{
CReaderThread m_thread;
};
#define WM_MESSAGE_TEST (WM_USER+1)
BEGIN_MESSAGE_MAP(CReaderThread, CWinThread)
ON_THREAD_MESSAGE( WM_MESSAGE_TEST, OnMessageTest )
END_MESSAGE_MAP()
BOOL Ctest7445App::InitInstance()
{
...
m_thread.m_bAutoDelete = 0;
m_thread.CreateThread();
...
return TRUE;
}
void Ctest7445App::OnAppAbout()
{
m_thread.PostThreadMessageW(WM_MESSAGE_TEST, 11, 22);
}
That's the additional to the default MFC project.
Re: How to manage user messege sent by PostThreadMessage
Quote:
Originally Posted by
aragornx
Code:
BOOL CReaderThread::InitInstance() {
TRACE( _T("CReaderThread::InitInstance() START\r\n") );
if ( reader != NULL ) {
if ( start() == true ) {
mainLoop();
}
}
stop();
TRACE( _T("CReaderThread::InitInstance() STOP\r\n") );
AfxEndThread(0);
return TRUE;
}
The code in bold text is wrong. It is always wrong to do something extensive in InitInstance(). The purpose of InitiInstance) is initialization only, after which you should simply return TRUE so as to allow the built-in message loop to commence. Your code, on the other hand, traps the InitiInstance() function, by calling your mainLoop() function forever, and never allows InitInstance() to return. Thus, you block the built-in message loop from ever even starting.
Re: How to manage user messege sent by PostThreadMessage
Incidentally, it is always a bad architecture to use PostThreadMessage for posting messages to a thread that has any form of a visible window. If the thread hosts any form of a visible window, then the messages posted to it will inevitably be lost under very common circumstances.
Mike