如何在GUI更新期间保持Delphi App响应?

时间:2010-02-02 11:15:14

标签: delphi user-interface

这个问题是关于在长时间运行的任务期间保持GUI响应(在大多数情况下几秒钟)。

我广泛使用线程和任务模式在后台线程中执行昂贵的任务。但是GUI更新需要一些时间呢?例如,填充大字符串网格或树视图?线程在这里没有帮助,因为无论如何都需要与主线程同步。

我知道Application.ProcessMessages的问题,但目前它似乎是在GUI更新方法中调用ProcessMessages的唯一解决方案。

有更好的想法吗?

6 个答案:

答案 0 :(得分:5)

填写网格,列表,数据集等时,请调用BeginUpdate / EndUpdate DisableControls / EnableControls。这将节省您的时间。我还有一个线程做了一些计算,但是GUI很慢,直到我在被修改的数据集上调用DisableControls并且因为控件在另一个标签页上而不可见。

此外,在更新控件时,请准备好您需要的所有数据,这样您就可以只填充列表,而无需进行可能会降低速度的计算。

答案 1 :(得分:5)

IMO如果GUI更新是瓶颈(即使使用BeginUpdate / EndUpdate作为@The_Fox建议),那么是时候重新考虑使用的GUI控件了。标准网格,树视图,列表框不仅仅是用于处理大量项目。为此目的,有许多高性能的第三方控件都是免费的和商业的。

对于初学者,如果瓶颈在网格,树视图或列表框上下文中,请查看VirtualTreeview。

答案 2 :(得分:4)

您的案例中Application.ProcessMessages有什么问题? Application.ProcessMessages方法正是针对这种情况。 Application.ProcessMessages的问题是这样的代码:

repeat
  Application.ProcessMessages;
until SomethingHappens;

这很糟糕,因为它是无用的CPU负载,应该用

代替
repeat
  Application.HandleMessage;
until SomethingHappens;

为其他线程提供处理器时间。单个Application.ProcessMessages调用(不在循环中)都可以。

答案 3 :(得分:1)

看看ActiveSleep

答案 4 :(得分:1)

如果您只想处理绘制消息而不处理其他内容:使用以下代替Application.ProcessMessages:

procedure ProcessPaintMessages;
var
  Msg: TMsg;
  i: Integer;
begin
  i := 0;
  repeat
    if Windows.PeekMessage(Msg, 0, 0, 0, PM_REMOVE or (QS_PAINT shl 16)) then begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end else Break;
    Inc(i);
  until i > 1000; // Breakout if we are in a paint only loop!
end;

答案 5 :(得分:-2)

您是否尝试过Indy的AntiFreeze组件?