Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this thread freezes my app on destruction?

I'm sure it's related to the GetMessage call as if I replace it with 'while(not terminated) do;', the app'd close peacefully. Is it because GetMessage freezes the thread? Could you give more info about the problem itself and eventually a solution. Thanks!

type TListener = class(TThread)
  procedure Execute; override;
  destructor Destroy; override;
end;

var l: TListener;
    msg:TMsg;

procedure TListener.Execute;
begin
  while(not Terminated) do
    while(GetMessage(msg, Cardinal(-1), 0, 0)) do;
end;

destructor TListener.Destroy;
begin
  inherited; // <-- freeze here!
end;

begin
  l:= TListener.Create();
  sleep(1000);
  l.Free;
end.
like image 656
netboy Avatar asked Aug 05 '11 17:08

netboy


1 Answers

Consider the termination condition of your inner loop. GetMessage blocks until a message arrives, and it only returns False when it processes a wm_Quit message.

The thread that calls Free on your TThread is waiting for the other thread to terminate — TThread.Destroy calls WaitFor. But your thread never terminates because it evidently never receives a wm_Quit message.

Since you're already using messages, don't bother checking Terminated. That only checks whether someone has called Terminate on your thread object, but since doing so clearly isn't the way to notify the thread that it should stop running, it's pointless to check it. (If the Terminate method were virtual, you could override it and have it post a wm_Quit message to the thread, but it isn't, so you can't.)

like image 139
Rob Kennedy Avatar answered Oct 14 '22 03:10

Rob Kennedy