线程消息循环在Delphi中挂起

时间:2010-03-22 20:56:27

标签: delphi multithreading message-queue messages tthread

我正在处理一个简单的Delphi程序,我正在尝试使用线程将程序的功能与其GUI分离,并在更冗长的任务中保持GUI响应等。基本上,我有一个'控制器'TThread和一个'视图'TForm。视图知道控制器的句柄,它用于通过PostThreadMessage发送控制器消息。我过去没有问题使用这种模型用于不是主要形式的表单,但出于某种原因,当我尝试将此模型用于主表单时,线程的消息循环才会退出。

这是我的线程消息循环代码:

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;

要设置控制器,我这样做:

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

为了处理主要表单的消息,我尝试使用Application.Run和以下循环(紧跟在Controller.Resume之后)

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

我已经被困在这里 - 任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

我基本上按原样测试了你的代码,它运行正常。尝试在GetMessage返回-1后添加对GetLastError的调用,以查看问题所在。

代码中是否在控制器线程中创建窗口并不完全清楚,但如果没有,我建议将-1而不是0作为HWND传递给GetMessage,并删除TranslateMessage / DispatchMessage调用,因为在它们之后的case语句应该处理你收到的任何消息。

此外,您不需要对错误执行“同步(终止)”。 Terminate只是将“Terminated”布尔值设置为true,因此您不需要同步它,您也可以轻松地使用“Break”来打破循环,效果相同。

答案 1 :(得分:0)

while循环的“结束”在哪里? 我想你会失踪并结束。所以也许(取决于实际的代码),你在一个声明中无休止地陷入while not Terminated do循环。