Hi,

I'm encountering a frustrating problem in Delphi.

I've written several very long programs to demonstrate certain things related to neural networks. As such, the program GUI has many things on it that are updated per iteration of the solver: from labels, to memos, to editstrings, etc.

The two main buttons are "Perform one iteration" of the solution process, and "Iterate" which loops the single iteration code based on a spinedit field value.

Everything works perfectly when programming/debugging. The dynamic visual of the screen updates is just what I need for my demonstration.

When the compiled program is run stand-alone, though, the single iteration works fine, and I can click, click, click it. But if I use the looped mode, running 100 iterations, say, so I can stand back and watch the updates, the program goes off to never-never land. The title bar does not say "(Not Responding)", but that's what it feels like. When enough time passes so that the iterations are completed, the screen updates to its final state and the program is okay again. But I want to see the evolution (the two or three Repaints inside each run of the iteration loop).

I don't understand what causes this behavior. I see the same behavior in other recent programs that involve iteration. Is there something I should be doing inside my iteration loop to avoid this behavior?

Stuck,

Joe

Dani AI

Generated

This is the classic case of the VCL main thread being starved by a tight loop: while your solver runs on the GUI thread, Windows messages (WM_PAINT, mouse/keyboard, etc.) cannot be processed, so the window looks frozen until the loop finishes. As hinted, the debugger can mask this by slowing execution or otherwise allowing messages to be processed, which is why you saw different behavior when running inside the IDE.

Two practical, reliable approaches:

  • Keep heavy work off the UI thread. Move the iteration loop into a worker thread and marshal only brief UI updates back to the main thread. Use TThread.Synchronize (blocks worker) or TThread.Queue/PostMessage (non‑blocking) to update controls. Update the GUI only every N iterations to avoid thrashing the UI.

  • If you must run on the main thread (quick demo), yield periodically instead of looping nonstop: update a cached status and let the message pump run occasionally. Calling Application.ProcessMessages works but is risky (reentrancy) and hurts performance, so call it rarely and disable controls while the loop runs.

Example worker-thread pattern (keeps UI updates safe and simple):

type
  TWorkerThread = class(TThread)
  private
    FProgress: Integer;
    procedure UpdateUI;
  protected
    procedure Execute; override;
  end;

procedure TWorkerThread.Execute;
var i: Integer;
begin
  for i := 1 to 1000 do
  begin
    // heavy computation here
    FProgress := i;
    Synchronize(UpdateUI); // or use TThread.Queue(UpdateUI) if available
  end;
end;

procedure TWorkerThread.UpdateUI;
begin
  Form1.Label1.Caption := IntToStr(FProgress);
end;

Extra tips: disable UI controls while iterating, limit UI refresh rate (e.g., every 5–50 iterations), and prefer Queue/PostMessage for responsiveness. For demonstration purposes only, use Application.ProcessMessages sparingly and with caution.

If you are in a tight loop that takes lots of processing power...You never process any of the window messages...It's easy to fix in Applications...just add Application.ProcessMessages in an iteration of your loop. This will allow your windows to process any messages that are in the queue...like repainting and such. There are other tricks...like putting heavily intensive code in it's own thread.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.