Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi thread not receiving messages

I am developing an application with multithreading (RAD Studio XE5). At the start of the application I create a single thread that will live as long as the main form does.

I am able to dispatch messages from the thread to any form that has been created in my application, however I can't find a way to do the opposite, sending a message from the main VCL thread to the worker thread.

When creating the main form I create the worker thread and copy the handle in a public variable:

  serverThread := TMyThread.Create(True, ServerPort + 1);
  serverThreadHandle := serverThread.Handle; // SAVE HANDLE
  serverThread.Start;

then (from a different form FrmSender) I dispatch a message to the thread:

  PostMessage(uMain.serverThreadHandle, UM_LOC_VCLMSG, UM_LOC_VCLMSG, Integer(PStrListVar));

This is the thread's Execute procedure:

procedure TMyThread.Execute;
var
    (..)
    vclMSG : TMsg;
    str1, str2 : string;
    (..)
begin
    while not(Terminated) do
    begin
        Sleep(10);
        if Assigned(FrmSender) then
          if FrmSender.HandleAllocated then
            if PeekMessage(vclMSG, FrmSender.Handle, 0, 0, PM_NOREMOVE) then
              begin
                if vclMSG.message = UM_LOC_VCLMSG then
                  begin
                    try
                      pStrListVar := pStrList(vclMSG.lParam);
                      str1 := pStrListVar^.Strings[0];
                      str2 := pStrListVar^.Strings[1];
                    finally
                      Dispose(pStrListVar);
                    end;
                  end;
              end;  
        (.. do other stuff ..)
    end;
end;

However PeekMessage() never returns true as if it was never receiving any message. I've tried changing the parameters to PeekMessage():

PeekMessage(vclMSG, 0, 0, 0, PM_NOREMOVE);

But with no results. Any ideas?

like image 442
tsmr Avatar asked Dec 25 '22 00:12

tsmr


1 Answers

From MSDN PostMessage function documentation:

Places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.

To post a message in the message queue associated with a thread, use the PostThreadMessage function.

Thus, you should use PostThreadMessage:

Posts a message to the message queue of the specified thread. It returns without waiting for the thread to process the message.

Give special attention to the Remarks section. The recipient thread needs a message queue. Force the thread having one by following these steps:

  • Create an event object, then create the thread.
  • Use the WaitForSingleObject function to wait for the event to be set to the signaled state before calling PostThreadMessage.
  • In the thread to which the message will be posted, call PeekMessage as shown here to force the system to create the message queue.

    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)
    
  • Set the event, to indicate that the thread is ready to receive posted messages.

Then, when using PeekMessage, you pass a handle value of -1 to the function, as documented.

like image 178
René Hoffmann Avatar answered Jan 14 '23 23:01

René Hoffmann