Search code examples
multithreadingdelphidelphi-2007

Updating each thread's timer in a TListView without CPU overload


Delphi used: 2007

Hello everyone,

I have a TListView with ViewStyle set to vsReport. When I click on a button, I launch about 50 threads. Each thread has a TListItem component. Each TListItem has a SubItem that is a timer. It starts at 250 and goes all the way down to 0. The user is able to see each timer decreasing in the TListView.

I have written the following code:

procedure TThreadWorker.DeleteTickets;
begin
 ListItem.Delete;
end;

procedure TThreadWorker.UpdateTimer;
begin
 ListItem.SubItems[1] := IntToStr(Timer);
end;

procedure TThreadWorker.TimerCounter;
begin
 Timer := 300;
 repeat
  Sleep(1000);
  Dec(Timer);
  Synchronize(UpdateTimer);
 until (Timer = 0);
 Synchronize(DeleteTickets);
end;

And... it works! But here's the thing: all these synchronizations seem to unnecessarily overload the CPU. Obviously, it's a bigger problem when I launch more threads (100, 200 or 300) or when I use a weaker computer. At first, I wasn't sure it was the synchronizations; but if I deactivate them, the CPU is no more overloaded.

To be frank, it's not that much of an issue. However, I have the feeling that decrementing timers shouldn't cause any sort of CPU overload: my code is probably not right. I tried calling UpdateTimer less often, and while it softens the CPU overload, it doesn't fix it in the end. Furthermore, I'd like the user to see the timer updated each second. The timer also needs to be as precise as possible.

Thank you.


Solution

  • I think you have placed the cart ahead of the horse here. Having all your threads synchronize into the main thread, each with their own timer and message queue, will place a heavy burden on the system. What's more, often times you don't want to burden your threads with running a message loop.

    A better approach in my view is to place a single timer in the main thread. When it ticks, have it retrieve progress from each thread or task that it needs to report on. You'll need to serialize access to that progress, but that's not expensive.