5

I have a simple Delphi program that I'm working on, in which I am attempting to use threading to separate the functionality of the program from its GUI, and to keep the GUI responsive during more lengthy tasks, etc. Basically, I have a 'controller' TThread, and a 'view' TForm. The view knows the controller's handle, which it uses to send the controller messages via PostThreadMessage. I have had no problem in the past using this sort of model for forms which are not the main form, but for some reason, when I attempt to use this model for the main form, the message loop of the thread just quits.

Here is my code for the threads message loop:

procedure TController.Execute;
var
  Msg : TMsg;
begin
  while not Terminated do begin
    if (Integer(GetMessage(Msg, hwnd(0), 0, 0)) = -1) then begin
      Synchronize(Terminate);
    end;

    TranslateMessage(Msg);
    DispatchMessage(Msg);

    case Msg.message of
      // ...call different methods based on message
    end;
  end;
end;

To set up the controller, I do this:

Controller := TController.Create(true); // Create suspended
Controller.FreeOnTerminate := True;
Controller.Resume;

For processing the main form's messages, I have tried using both Application.Run and the following loop (immediately after Controller.Resume)

while not Application.Terminated do begin
  Application.ProcessMessages;
end;

I've run stuck here - any help would be greatly appreciated.

  • 1
    Welcome to Stack Overflow, erikjw! I hope you find a good answer. Quick note, though. It makes your code harder to read when you put a `begin` on the same line as the `do` or the `then` before it. That's considered good style in C, but in Delphi most of us prefer to put it on its own line so we can line up `begin` and `end` pairs visually. – Mason Wheeler Mar 22 '10 at 22:56
  • Thanks for all of the replies so far. I've tried each of them separately, as well as some different combinations, and I'm still having issues. When I do a debug, and step through the code in `TController.Execute`, as soon as I step over `GetMessage`, no matter what I pass as the hwnd, it just doesn't keep going through the loop. It doesn't execute any statements after the loop, it just inexplicably stops. And what is even more confusing is that I see no indication that the thread itself has actually died. – Erik Westenbroek Mar 23 '10 at 00:29
  • Have you tried removing `Synchronise()`? If there is no message loop running, it may just fail. Also, which version of Delphi are you using? – Nat Mar 23 '10 at 01:11
  • 6
    I completely disagree with you, @Mason. The `begin` on its own line is visual noise. The indentation alone tells all that's needed. Stash the noise at the end of the line so it's out of the way. – Rob Kennedy Mar 23 '10 at 03:53
  • 2
    Erik, it's not clear from your statements, but you do know that GetMessage blocks, right? It's not going to execute anything more in your loop until you call PostThreadMessage. – Zoë Peterson Mar 23 '10 at 04:03
  • Aha! I was not aware that GetMessage blocked. I guess I should be looking some other places for errors, not just the message loop. Thanks! – Erik Westenbroek Mar 23 '10 at 12:10

2 Answers2

3

I tested your code basically as-is and it worked fine. Try adding a call to GetLastError after GetMessage returns -1 to see what the problem is.

It's not completely clear from the code whether you're creating windows within the controller thread, but if not, I'd suggest passing -1 instead of 0 as the HWND to GetMessage, and remove the TranslateMessage/DispatchMessage calls, since the case statement that follows them should handle any messages you receive.

Also, you don't need to do "Synchronize(Terminate)" on an error. Terminate just sets the "Terminated" boolean to true, so you don't need to synchronize it, and you could just as easily use "Break" to break out of the loop with the same effect.

Zoë Peterson
  • 13,094
  • 2
  • 44
  • 64
0

Where's the "end" for the while loop? I think you're missing and end. So maybe (depending on the actual code), you're stuck in the while not Terminated do looping endlessly on a single statement.

Chris Thornton
  • 15,620
  • 5
  • 37
  • 62