【问题标题】:Thread Message Loop Hangs in DelphiDelphi中的线程消息循环挂起
【发布时间】:2010-03-23 13:55:12
【问题描述】:

我正在开发一个简单的 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;

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

【问题讨论】:

  • 欢迎来到 Stack Overflow,erikjw!我希望你能找到一个好的答案。不过请注意。当您将begindothen 放在它之前的同一行时,它会使您的代码更难阅读。这在 C 中被认为是很好的风格,但在 Delphi 中,我们大多数人更喜欢将它放在自己的行中,这样我们就可以在视觉上排列 beginend 对。
  • 感谢到目前为止的所有回复。我已经分别尝试了它们中的每一个,以及一些不同的组合,但我仍然遇到问题。当我进行调试并单步执行TController.Execute 中的代码时,只要我越过GetMessage,无论我作为hwnd 传递什么,它都不会继续循环。它在循环之后不执行任何语句,它只是莫名其妙地停止。更令人困惑的是,我没有看到线程本身实际上已经死亡的迹象。
  • 你试过删除Synchronise()吗?如果没有消息循环运行,它可能会失败。另外,您使用的是哪个版本的 Delphi?
  • 我完全不同意你的观点,@Mason。 begin 单独一行是视觉噪音。仅缩进就说明了所有需要。把噪音藏在线路的末端,这样它就不会碍事了。
  • Erik,您的陈述并不清楚,但您知道 GetMessage 会阻塞,对吗?在您调用 PostThreadMessage 之前,它不会在您的循环中执行更多操作。

标签: delphi multithreading message-queue messages tthread


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    while 循环的“结束”在哪里? 我想你失踪了,结束了。所以也许(取决于实际的代码),你被困在while not Terminated do 在一个语句上无休止地循环。

    【讨论】:

    • 那是我的错,我会在问题中解决这个问题 - 循环几乎包含了整个函数。
    猜你喜欢
    • 2010-09-18
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    相关资源
    最近更新 更多