Reputation: 24274
In one C++ application I have a window whose message loop runs in a separate thread because the main thread is busy calculating and rendering a simulation. The window acts as a log window for the simulation. When the simulation throws an exception, the simulation closes and the log window displays the details.
Now the main thread should wait until the log window is closed. Since the message loop runs on a separate thread, I tried to
WaitForSingleObject(logwindow->thread, INFINITE);
from the main thread.
However, this seems to block the message pump and the log window freezes. So how do I correctly wait until a window is closed or a thread ends?
ED: The window is created on the main thread but runs on a different thread. I'll go ahead and change it so it creates on the message loop thread too.
Upvotes: 2
Views: 2429
Reputation: 596713
The fact that the log window is freezing while the main thread is in a blocking wait suggests the worker thread is sending a message to the main thread and then waiting for a reply, but the main thread is already blocked and cannot reply to it. That is a classic deadlock situation for both threads. You should use MsgWaitForMultipleObjects()
instead of WaitForSingleObject()
in the main thread to detect when new messages need processing while waiting, eg:
do
{
DWORD dwRet = MsgWaitForMultipleObjects(1, &(logwindow->thread), FALSE, INFINITE, QS_ALLINPUT);
if (dwRet == 0xFFFFFFFF) break;
if (dwRet == (WAIT_OBJECT_0 + 1))
{
process messages here...
}
}
while (dwRet != WAIT_OBJECT_0);
I agree with David that you really should be doing all UI work in the main thread and do your calculations in the worker thread, not the other way around.
Upvotes: 0
Reputation: 613083
You have a few options.
PostMessage
or SendMessage
.MsgWaitForMultipleObjects
for your wait. To elaborate on MsgWaitForMultipleObjects
, it's a wait function that can be configured to return when messages arrive in the queue. Thus you can keep your message pump alive whilst also using a blocking wait in between processing queued messages.
In pseudo-code you would write it like this:
do
{
WaitResult = MsgWaitForMultipleObjects(1, hThread, TRUE, INFINITE, QS_ALLEVENTS);
if (WaitResult == MessageArrivedOnQueue)
PumpMessageQueue();
} while (WaitResult != WaitHandlesSignaled)
Upvotes: 2