jpfollenius
jpfollenius

Reputation: 16620

Howto keep Delphi App Responsive during GUI Updates?

This question is about keeping the GUI responsive during longer-running tasks (a few seconds in most cases).

I extensively use threads and a task pattern to execute expensive task in a background thread. But what about GUI updates that takes some time? For example, filling a large string grid or tree view? A thread does not help here because everything needs to be synchronized with the main thread anyway.

I know the problems of Application.ProcessMessages, but currently it seems like the only solution to put calls to ProcessMessages inside the GUI update methods.

Any better ideas?

Upvotes: 5

Views: 4002

Answers (6)

utku_karatas
utku_karatas

Reputation: 6313

IMO if the GUI update is the bottleneck (even if BeginUpdate/EndUpdate is used as @The_Fox suggests) then it is time to reconsider the GUI controls used. The standart grids, treeviews, listboxes aren't simply cut for handling very large number of items. There are many performant thirdparty controls both free and commercial for that purpose.

For a starter, check out VirtualTreeview if the bottleneck is in a grid, treeview or a listbox context.

Upvotes: 5

Ritsaert Hornstra
Ritsaert Hornstra

Reputation: 5111

If you only want to process paint messages and nothing else: use the following instead of 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;

Upvotes: 1

The_Fox
The_Fox

Reputation: 7062

When filling Grids, Lists, DataSets etc., call BeginUpdate/EndUpdate DisableControls/EnableControls. This will save you time. I also had a thread that did some calculations, but nevertheless the GUI was slow, until I called DisableControls on the datasets that were being modified and not visible because the controls are on another tabsheet.

Also, when updating controls, have all the data you need prepared, so you can just fill your list, without doing calculations that can slow this down.

Upvotes: 5

kludg
kludg

Reputation: 27493

What's wrong with Application.ProcessMessages in your case? The Application.ProcessMessages method is exactly for such cases. The problem with Application.ProcessMessages is the code like this:

repeat
  Application.ProcessMessages;
until SomethingHappens;

That is bad since it is useless CPU load, and should be replaced by

repeat
  Application.HandleMessage;
until SomethingHappens;

which yields processor time to other threads. Single Application.ProcessMessages calls (not in loop) are OK.

Upvotes: 4

Crudler
Crudler

Reputation: 2286

Have you tried out the AntiFreeze component from Indy?

Upvotes: -2

gabr
gabr

Reputation: 26850

Take a look at ActiveSleep.

Upvotes: 1

Related Questions