代码之家  ›  专栏  ›  技术社区  ›  6String_Coder

TAniIndicator未旋转-加载tlistview

  •  1
  • 6String_Coder  · 技术社区  · 7 年前

    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;
    

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

    1 回复  |  直到 4 年前
        1
  •  2
  •   Remy Lebeau    7 年前

    Process() 方法,该方法正在由调用 TThread.Synchronize() 因此它在主UI线程中运行。 没有处理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;