views:

471

answers:

2

Hello all. 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.

A: 

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
Thats my bad, i'll fix that in the question - the loop encompasses pretty much the entire function.
Erik Westenbroek
+1  A: 

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.

Craig Peterson