Search code examples
delphiomnithreadlibrary

How to update progress indicator from a second thread?


I have a main form with a progress indicator on it. In the datamodule I've ten datasets, each of them has an OnBeforeOpen event defined.

I would like to show through the progress bar in the main form a percentage of progress of the opened datasets.

Since I'm completely new to multithreading programming, can someone please give me some advice?

Thank you very much


Solution

  • Either post a message from the thread to the main thread and update the progress bar from there or use the TThread.Queue method to execute some code in the context of the main thread.

    unit Unit12;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls;
    
    const
      WM_UPDATE_PB = WM_USER;
    
    type
      TForm12 = class(TForm)
        ProgressBar1: TProgressBar;
        ProgressBar2: TProgressBar;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
      public
        procedure WMUpdatePB(var msg: TMessage); message WM_UPDATE_PB;
      end;
    
    var
      Form12: TForm12;
    
    implementation
    
    {$R *.dfm}
    
    procedure UpdateFromThreadViaMessage;
    var
      i: integer;
    begin
      for i := 1 to 100 do begin
        Sleep(20);
        PostMessage(Form12.Handle, WM_UPDATE_PB, i, 0);
      end;
    end;
    
    procedure UpdateFromThreadViaQueue;
    var
      i: integer;
    begin
      for i := 1 to 100 do begin
        Sleep(20);
        TThread.Queue(nil,
          procedure begin
            Form12.ProgressBar2.Position := i;
          end);
      end;
    end;
    
    procedure TForm12.Button1Click(Sender: TObject);
    begin
      TThread.CreateAnonymousThread(UpdateFromThreadViaMessage).Start;
      TThread.CreateAnonymousThread(UpdateFromThreadViaQueue).Start;
    end;
    
    procedure TForm12.WMUpdatePB(var msg: TMessage);
    begin
      ProgressBar1.Position := msg.WParam;
    end;
    
    end.