Delphi中的线程消息循环挂起

5
我有一个简单的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;

我卡在这里了 - 希望得到帮助,非常感谢。

1
欢迎来到Stack Overflow,erikjw!希望您能找到一个好的答案。但是,需要注意一点的是,当您将begin放在与其前面的dothen同一行时,会使您的代码更难以阅读。虽然这在C语言中被认为是良好的编码风格,但在Delphi中,我们大多数人更喜欢将其单独放在一行,以便我们可以通过视觉对齐beginend成对出现的位置。 - Mason Wheeler
感谢迄今为止所有的回复。我已经分别尝试了每一个回复,以及一些不同的组合,但仍然存在问题。当我进行调试并在TController.Execute中逐步执行代码时,无论我传递什么hwnd,只要我跨越GetMessage,它就不会继续通过循环。它不会执行循环后的任何语句,它只是莫名其妙地停止了。更令人困惑的是,我看不到线程本身实际上已经死亡的任何迹象。 - Erik Westenbroek
你尝试过移除 Synchronise() 吗?如果没有消息循环在运行,它可能会失败。另外,你使用的是哪个版本的 Delphi? - Nat
6
我完全不同意你的看法,@Mason。单独一行的 begin 是视觉上的噪音。仅凭缩进就足以表明所有必要的信息。将这个噪音藏在行尾,这样就不会影响阅读了。 - Rob Kennedy
2
Erik,从你的陈述中并不清楚,但你知道GetMessage会阻塞线程,对吧?在调用PostThreadMessage之前,它不会在你的循环中执行任何其他操作。 - Zoë Peterson
啊哈!我没有意识到 GetMessage 是会阻塞的。我想我应该寻找其他地方的错误,而不仅仅是消息循环。谢谢! - Erik Westenbroek
2个回答

3

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

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

此外,在出现错误时,你不需要执行 "Synchronize(Terminate)" 操作。Terminate 只是将 "Terminated" 布尔值设置为 true,因此你不需要同步它,而且可以使用 "Break" 来退出循环并产生相同的效果。


0

while循环的“end”在哪里? 我认为你缺少了一个end。所以,也许(根据实际代码),你被困在while not Terminated do的循环中,无限地执行单个语句。


这是我的错,我会在问题中修复它 - 这个循环几乎包含了整个函数。 - Erik Westenbroek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接