Application.ProcessMessages 挂起?

X-R*_*Ray 3 delphi vcl delphi-2009

我的单线程 delphi 2009 应用程序(尚未完成)已经开始出现 Application.ProcessMessages 挂起的问题。我的应用程序有一个 TTimer 对象,它每 100 毫秒触发一次以轮询外部设备。我使用 Application.ProcessMessages 在发生变化时更新屏幕,以便应用程序仍然响应。

其中之一是在网格 OnMouseDown 事件中。在那里,它有一个基本上挂起的 Application.ProcessMessages。删除它没有问题,只是我很快发现了另一个也阻塞的 Application.ProcessMessages。

我认为可能发生在我身上的事情是 TTimer 处于我目前正在调试的应用程序模式下可能需要很长时间才能完成。我已阻止 TTimer.OnTimer 事件处理程序重新输入相同的代码(见下文):

procedure TfrmMeas.tmrCheckTimer(Sender: TObject);
begin
  if m_CheckTimerBusy then
    exit;

  m_CheckTimerBusy:=true;
  try
    PollForAndShowMeasurements;
  finally
    m_CheckTimerBusy:=false;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

在哪些地方调用 Application.ProcessMessages 是不好的做法?OnPaint 例程会让人想起毫无意义的东西。

任何一般建议?

我很惊讶地看到在开发过程中出现这种问题!

Vik*_*vub 5

我的建议TApplication.ProcessMessages永远不要使用它 - 根本没有放置它的好地方。

想象一下调用它的作用:您的应用程序运行一个消息循环 - 窗口消息(由操作系统、其他应用程序、您的应用程序等产生)按顺序处理 - 在那里,在其中一个消息处理的中间,您只需重新- 再次运行整个消息循环,无需控制将处理哪些消息,将有多少消息,是否有任何消息将进入其自己的消息循环......以及它们是否有任何重入问题. 这就是我所说的招惹麻烦

有时有很好的理由来处理一些窗口消息(特别是不挂起其他线程),或者处理指向特定窗口的所有消息,但这可能会以更微妙的方式完成,并有更多的控制。

如果您必须在主 GUI 线程中进行任何处理,并且您只想更新界面,则可以使用该TWinControl.Repaint方法重绘 GUI 元素。
如果您想让应用程序对用户输入保持响应,您基本上必须使用后台/工作线程。

注意:在 Delphi 中,在主线程中进行任何长时间处理时,特别是如果涉及等待,您应该CheckSynchronize定期调用,以允许任何其他线程与主线程同步 - 它们可能(并且可能会)挂起。
VCL 仅在应用程序空闲和处理WM_NULL消息时调用它(假设什么都不做,这也可能导致一些有趣的副作用)。