I am implementing a thread that needs the following features:
- Promptly responds to termination requests
- Pumps messages
- Remains responsive to SendMessage requests while waiting for a message
My initial implementation of the message pump used GetMessage like:
while not Terminated and GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
The problem I found with that, is that GetMessage will never return unless there is a message.
Meaning, if there is low message activity, it may be quite a while before it checks Terminated again.
My second implementation (inspired by this answer) used MsgWaitForMultipleObjects to wait until a message exists before checking (since it has a timeout)
while not Terminated do
begin
if MsgWaitForMultipleObjects(0, nil^, False, 1000, QS_ALLEVENTS) = WAIT_OBJECT_0 then
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
end;
The problem I've found with this, is that MsgWaitForMultipleObjects blocks the thread while it waits. So, when a message is sent to the thread via SendMessageTimeout, it times out, where it doesn't when using GetMessage.
The solution that comes to mind is to go back to the GetMessage implementation, but add a timer to make sure a WM_TIMER message resets the loop every second.
Is this really the only way to do this? It seems there should be some better way to keep the thread responsive while waiting for messages.