How to update progress indicator from a second thread?
Asked Answered
I

1

5

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

Iy answered 3/4, 2013 at 8:54 Comment(3)
See Delphi - Synchronize Thread with Frame. Seems like a duplicate for your question. An example how to do this with a PostMessage() is provided.Benighted
what does OTL have to do here ? for the moment you described not even single-threaded program, but just a static, paused in breakpoint one. You have a static state and want to display it. Well, a lot of options exists, starting with Application.OnIdle. If you sure you have some very special conditions, that require mixing multithreading concept into the question, then perhaps you can reveal a bit about your program, its overall design, sources. catb.org/esr/faqs/smart-questions.html As of now there's nothing about multithreading in ur question, it is about simple 1-thread app yetMarque
Why do you need to Thread for this? simply update your progress indicator on the OnBeforeOpen event.Microcircuit
T
11

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.
Tonality answered 3/4, 2013 at 9:9 Comment(4)
thank you: in the end I used the UpdateFromThreadViaQueue and it worked quite well. I choose your answer since it helped me to understand how thread messages and thread queues work. After studying your answer as well as all the other answers to my question, I now can understand why using threads in this specific case is not necessary.Iy
@Fabio OTL has it's own messaging primitives, which basically use PostMessage, but are more in line with OTL style For example otl.17slon.com/book/… but also demoes and OTL developer blog articles.Marque
@Arioch thank you very much for pointing me to OTL's resources: I will study the examples in itIy
??? how could you download and use OTL without knowing there are OTL resources ?Marque

© 2022 - 2024 — McMap. All rights reserved.