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.

6
  • 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. Commented Mar 22, 2010 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. Commented Mar 23, 2010 at 0: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? Commented Mar 23, 2010 at 1: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. Commented Mar 23, 2010 at 3: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. Commented Mar 23, 2010 at 4:03

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

1 Comment

Thats my bad, i'll fix that in the question - the loop encompasses pretty much the entire function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.