How to current close window while messages still in queue
Hi All,
Here is my scenario:
I have an MFC application. In one of the dialogs, I have a worker thread.
Here's how I start the thread:
m_pThread = AfxBeginThread((AFX_THREADPROC)LoadThread, this, 0, 0,
CREATE_SUSPENDED);
m_pThread->m_bAutoDelete = FALSE;
m_pThread->ResumeThread();
The thread reads some rows from a database (SELECT * ..), and then iterates
through the result set and sends the data rows one by one to the GUI to
update a GUI control:
for (int i = 0; i <= iUpperBound && (WaitForSingleObject(m_hQuitEvent, 0)
== WAIT_TIMEOUT); ++i)
{
/../
// Construct data, etc...
CData* pData = new CData; // pseudocode
PostMessage(UpdateMessage, (WPARAM)pData, ... ) // Update the GUI
and delete pData
}
After the for loop is over, the thread function just finishes and this
thread ends. The m_hQuitEvent is there so that I can set it if I want to
abort the processing.
Here is how the message handler looks like:
LRESULT CWhateverDialog::OnUpdateMessage(WPARAM wParam, ...)
{
CData* pData = (CData*)wParam;
// update GUI control w/ pData information
delete pData;
return 0;
}
The problem is that when I close the dialog, even though I wait for the
thread to complete (WaitForSingleObject on its handle -
CWinThread::m_hThread), there are still some messages in the message queue
that are not yet processed and so I end up having some memory leaks (because
the handler never gets a chance to be called to de-allocate the objects
allocated and postmessage'ed to the GUI.)
What is the correct way to handle this situation ?
Here is what I tried:
I have added two variables: m_iMessagesProcessed and m_iMessagesToProcess. I
increment m_iMessagesToProcess in the thread, and I increment the
m_iMessagesProcessed in the message handler.
Then, I have another thread that basically does this:
while (m_iMessagesProcessed < m_iMessagesToProcess)
{
Sleep (50);
}
PostMessage(MSG_OkToQuit, ... )
I know that it is not a good idea to use Sleep but I have no idea what else
to do here.. I just want to try again after a while and also allow other
threads to do their own thing. I could do a WaitForSingleObject on some
event that never gets signaled with a timeout of 50, but wouldn't that be
the exact same as sleep ? Anyway, 50 is just an arbitrary value; I know it
doesn't mean anything as Windows is not a realtime operating system... it is
there just as a "let's try again 'later'"...
Anyway, in the message handler for MSG_OkToQuit, I basically do a
CDialog::OnOK() to dimiss it. However, even though I confirmed that
m_iMessagesProcessed is equal to m_iMessagesToProcess, I still get memory
leaks.
If, however, I wait for the thread to finish sending all the data, I do not
get any memory leaks.
Therefore, it seems like I need to somehow make sure that I wait until all
the messages from the queue are processed but using a method different than
the above which doesn't seem to work.
BTW, I know for sure that it is a problem with messages being queued because
if I add a Sleep in the thread after the PostMessage, and I abort the
thread, I do not get the memory leaks. Therefore, it must be that by adding
that Sleep, there is a greater chance for all the messages to be processed.
Thanks and thank you for reading this long message,
vvf