TAniIndicator not spinning – loading a tlistview Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of TAniIndicator not spinning – loading a tlistview without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I’m new with the TAniindicator component, so for testing purposes I have put together a project that will build a listview and display/spin the Aniindicator whilst the listview is being built.

type
TLoadThread = class(TThread)
public
 constructor Create; reintroduce;
protected
 procedure Process;
 procedure Execute; override;
end;    

constructor TLoadThread.Create;
begin
 inherited Create(True);
 FreeOnTerminate := True;
end;

procedure TLoadThread.Process;
begin
 Form1.BuildListView;
end;

procedure TLoadThread.Execute;
begin
 inherited;
 FreeOnTerminate := True;
 Synchronize(Process);
end;

var _loadThread : TLoadThread;

procedure TForm1.ThreadTerminated(Sender: TObject);
begin  
 AniIndicator1.Enabled := False;
 AniIndicator1.Visible := False;
end;

procedure TForm1.BuildListView;
var i : integer;
    LI : TListViewItem;
 begin
  Listview1.BeginUpdate;
 try
  for i := 1 to 2000 do
  begin
   LI := Listview1.Items.Add;
   LI.Text := 'Listview Item ' + IntToStr(i);
  end;
 finally
  Listview1.EndUpdate;
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 AniIndicator1.Visible := False;
 _loadThread := nil;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 _loadThread := TLoadThread.Create;
 _loadThread.OnTerminate := ThreadTerminated;
 _loadThread.Start;
 AniIndicator1.Enabled := True;
end;

I thought I was on the right track but this doesn’t appear to work, can anyone explain what I’m doing wrong please?

Answer

Your worker thread is spending all of its time inside of its Process() method, which is being called by TThread.Synchronize() so it runs in the main UI thread. Process() is not processing UI messages, which is why TAniIndicator does not work.

As-is, your worker thread is completely useless. All of your code is running in the main UI thread. So, you may as well get rid of TLoadThread altogether:

procedure TForm1.FormCreate(Sender: TObject);
begin
  AniIndicator1.Visible := False;
end;

procedure TForm1.BuildListView;
var
  i : integer;
  LI : TListViewItem;
begin
  AniIndicator1.Visible := True;
  AniIndicator1.Enabled := True;
  ListView1.BeginUpdate;
  try
    for i := 1 to 2000 do
    begin
      LI := ListView1.Items.Add;
      LI.Text := 'ListView Item ' + IntToStr(i);
      if (i mod 100) = 0 then
        Application.ProcessMessages;
    end;
  finally
    ListView1.EndUpdate;
    AniIndicator1.Enabled := False;
    AniIndicator1.Visible := False;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  BuildListView;
end;

Otherwise, if you use a thread, do not synchronize the loop itself, only the pieces that actually touch the UI:

type
  TLoadThread = class(TThread)
  public
    constructor Create; reintroduce;
  protected
    procedure Execute; override;
  end;

constructor TLoadThread.Create;
begin
  inherited Create(True);
  FreeOnTerminate := True;
end;

procedure TLoadThread.Execute;
begin
  Form1.BuildListView;
end;

var
  _loadThread : TLoadThread = nil;

procedure TForm1.ThreadTerminated(Sender: TObject);
begin
  _loadThread := nil;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  AniIndicator1.Visible := False;
end;

procedure TForm1.BuildListView;
var
  i : integer;
begin
  TThread.Synchronize(nil,
   procedure
   begin
     AniIndicator1.Visible := True;
     AniIndicator1.Enabled := True;
     ListView1.BeginUpdate;
   end
  );
  try
    for i := 1 to 2000 do
    begin
      TThread.Synchronize(nil,
        procedure
        var
          LI : TListViewItem;
        begin
          LI := ListView1.Items.Add;
          LI.Text := 'ListView Item ' + IntToStr(i);
        end
      );
    end;
  finally
    TThread.Synchronize(nil,
      procedure
      begin
        ListView1.EndUpdate;
        AniIndicator1.Enabled := False;
        AniIndicator1.Visible := False;
      end
    );
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if _loadThread <> nil then
  begin
    _loadThread := TLoadThread.Create;
    _loadThread.OnTerminate := ThreadTerminated;
    _loadThread.Start;
  end;
end;
We are here to answer your question about TAniIndicator not spinning – loading a tlistview - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji