I have an MFC application that launches another process using CreateProcess(...)
. I would like to perform a UI update when the created process terminates. Normally, I would use WaitForSingleObject
or WaitForMutlipleObject
on the returned process HANDLE
but this will block the GUI thread (bad).
The only solution I can think of is to spawn a new thread that can wait on the handle and post a message when the process terminates. This is not ideal.
So is it possible to register the handle with the Windows Manager and receive a Windows message when the process terminates?
If you can modify the code of the child process, you may just add a back-channel that will inform the parent process by
SendMessage
when it is about to leave. If you cannot do that, you may create a relay process that will just pass-through the original child process data (if any) but will do the information job when the child left. This is, of course, least to say far less elegent than just using a dedicated thread and e.g.WaitForSingleObject
.Good news! Windows has exactly the API you're looking for: MsgWaitForMultipleObjects ().
Tricker, is to get this into MFC's message pump, but I found this link which recommends doing the following (code untested, fixed (!), and adapted to wait on just one handle):
I have to say that this code still doesn't look ideal to me, but it's probably close enough. I don't know enough about MFC to comment further.
Please note: This code won't see that the handle has been signalled until MFC passes through the message pump. That might happen while
MessageBox()
has control, for example. If that bothers you, consider using RegisterWaitForSingleObject instead, as recommended above by the legendary Raymond Chen.The solution is creating a thread when your app is created. You then wait on an event that should be pulsed when needed. Example:
Trigger thread into action:
You destroy the thread when your app is ending:
You can use
RegisterWaitForSingleObject()
to get notified via callback, when the process has ended. TheRegisterWaitForSingleObject
function directs a wait thread in the thread pool to wait on the process, so this should be optimal usage of resources. As Raymond Chen commented:A minimal example of a Win32 GUI application follows. The code creates a window, then it creates another instance of itself as a child process, which is indicated by the "/child" parameter. It registers the wait callback function and runs a regular message loop. You can resize and move the window to see that the GUI is not blocked. When the child process has ended, the system asynchronously calls the wait callback which posts an application-defined message (
WM_APP
) to the window. When the window receives the message, it immediately callsUnregisterWait()
to cancel the wait. As the reference states, even wait operations that useWT_EXECUTEONLYONCE
must be canceled when the wait is completed (but not from within the callback!). Then the window shows a message box to demonstrate that it has received the message.Error handling is omitted for brevity. You should check the return value of each API function and call
GetLastError()
in caseFALSE
is returned.Bonus OldNewThing read: Why bother with RegisterWaitForSingleObject when you have MsgWaitForMultipleObjects?
I would do one of these two:
Either call
WaitForSingleObject()
or whatever with a timeout of zero in your message loop somewhere (might have to change your loop toPeekMessage()
or addWM_TIMER
messages to make sure you check every so often,)Or better still, spawn a thread with a very small stack (you can customize that in the
CreateThread()
call) that only waits for this child process and then posts a message to your message loop.I like option 2 better, since a thread with a small stack that does nothing but wait for stuff is hardly a resource drain.