代码之家  ›  专栏  ›  技术社区  ›  jpfollenius Rob Kennedy

如何在GUI更新期间保持Delphi应用程序的响应?

  •  5
  • jpfollenius Rob Kennedy  · 技术社区  · 15 年前

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

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

    我知道的问题是 Application.ProcessMessages ,但目前似乎是唯一可以将呼叫 ProcessMessages 在GUI更新方法中。

    有更好的主意吗?

    6 回复  |  直到 12 年前
        1
  •  5
  •   utku_karatas    15 年前

    IMO如果图形用户界面更新是瓶颈(即使beginupdate/endupdate如@the_Fox建议的那样使用),那么是时候重新考虑使用的图形用户界面控件了。标准网格、树视图、列表框并不是简单地为处理大量项目而切割的。为了实现这一目标,有许多性能良好的第三方控制,包括免费控制和商业控制。

    对于初学者,如果瓶颈位于网格、树视图或列表框上下文中,请签出virtualTreeView。

        2
  •  5
  •   The_Fox    15 年前

    当填充网格、列表、数据集等时,调用beginupdate/endupdate disablecontrols/enableControls。这会节省你的时间。我也有一个执行一些计算的线程,但是GUI很慢,直到我在正在修改的数据集上调用了DisableControls,因为控件在另一个选项卡上而不可见。

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

        3
  •  4
  •   kludg    15 年前

    在您的案例中,application.processmessages有什么问题?application.processmessages方法完全适用于这种情况。application.processMessages的问题是如下代码:

    repeat
      Application.ProcessMessages;
    until SomethingHappens;
    

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

    repeat
      Application.HandleMessage;
    until SomethingHappens;
    

    它为其他线程提供处理器时间。单个application.processmessages调用(不在循环中)正常。

        4
  •  1
  •   gabr    15 年前

    看一看 ActiveSleep .

        5
  •  1
  •   Ritsaert Hornstra    15 年前

    如果只想处理paint消息,而不想处理其他任何消息:请使用以下内容而不是application.process messages:

    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;
    
        6
  •  -2
  •   Crudler    15 年前

    你试用过印地的防冻成分了吗?