0

Delphi 10.4 FMX (although I'm sure this is a general Delphi question)

My dialog window is reading a large file.

  AssignFile(theFile, OpenDialog1.FileName);

  Reset(theFile);

  while not EOF(theFile) and not CancelButtonPressed do
    begin
      ReadLn(theFile, theLine);
      Label1.Text := theLine;
      ProgressBar1.Value := PercentageOfFileRead;

      // Application.ProcessMessages;
    end;

  CloseFile(theFile);

Without the Application.ProcessMessages, the Label and ProgressBar are never painted. I don't think Application.ProcessMessages is the best way to go though as it tends to crash after a few thousand calls.

What is the best practice for repainting components during a batch process like this?

Mike at Bookup
  • 1,211
  • 14
  • 32
  • 2
    Use a thread, and call Synchronize. There's loads of examples around – Dave Nottage Jul 30 '20 at 01:22
  • 2
    Use the `Repaint()` method of the individual controls, or of the Form itself. Otherwise, move the file reading code to a worker thread that syncs with the main UI thread via `TThread.Synchronize()` or `TThread.Queue()` whenever it wants to update a UI control. – Remy Lebeau Jul 30 '20 at 01:24

1 Answers1

1

Something like this:

AssignFile(theFile, OpenDialog1.FileName);

Reset(theFile);

TThread.CreateAnonymousThread(PROCEDURE
                                BEGIN
                                  while not EOF(theFile) and not CancelButtonPressed do
                                  begin
                                    ReadLn(theFile, theLine);
                                    TThread.Synchronize(NIL,PROCEDURE
                                                              BEGIN
                                                                Label1.Text := theLine;
                                                                ProgressBar1.Value := PercentageOfFileRead;
                                                              END);
                                  end;
                                  CloseFile(theFile);
                                END);
HeartWare
  • 7,464
  • 2
  • 26
  • 30
  • 1
    But this is not best practice. If you are loading a file with 100M lines, you don't want to update the GUI *once per line* (maybe 100 000 times per second). You don't need that "frame rate", and the frequent GUI updates will make the operation an order of magnitude slower (or two or three)... Instead increase a counter on each line and update the UI when the counter is an even multiple of 10000 or something. Or compare tick counts (milliseconds). And feel free to stop using legacy Pascal I/O. (That might also increase performance significantly.) – Andreas Rejbrand Jul 30 '20 at 17:11
  • @AndreasRejbrand: Agreed. My code was simply a straight conversion of the original code to threaded version. – HeartWare Jul 31 '20 at 06:03