1

我是 TAniindicator 组件的新手,因此出于测试目的,我整理了一个项目,该项目将构建一个列表视图并在构建列表视图时显示/旋转 Aniindicator。

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;

我以为我在正确的轨道上,但这似乎不起作用,谁能解释我做错了什么?

4

1 回答 1

1

您的工作线程将所有时间都花在其Process()方法中,该方法正在被调用,TThread.Synchronize()因此它在主 UI 线程中运行。Process()不处理 UI 消息,这就是为什么TAniIndicator不起作用。

照原样,您的工作线程完全没用。您的所有代码都在主 UI 线程中运行。所以,你不妨完全摆脱TLoadThread

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;

否则,如果您使用线程,请不要同步循环本身,只同步实际接触 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;
于 2017-08-06T20:24:24.640 回答