在 Delphi 中使用匿名线程

xytpbqjk  于 2023-06-05  发布在  其他
关注(0)|答案(1)|浏览(269)

我尝试使用一个匿名线程来更新表单面板中的一个简单标签,以“动画”方式显示结束点,但它不起作用。我是一个使用线程的新手,您的帮助将非常有用。

procedure TFormEscolaImpresso.UpdateMsg(AShow: Boolean; AMsg: string);
begin
  lbMsg.Caption := AMsg;
  pnMsg.Visible := AShow;
  pnMsg.Update;

  if AShow then
  begin
    TThread.CreateAnonymousThread(
      procedure
      begin
        TThread.ForceQueue(TThread.CurrentThread,
          procedure
          begin
            while pnMsg.Visible do
            begin
              lbMsg.Caption := string(lbMsg.Caption).Replace('...', '');

              pnMsg.Update;
              lbMsg.Caption := lbMsg.Caption + '.';

              pnMsg.Update;
              lbMsg.Caption := lbMsg.Caption + '..';
              Sleep(2000);

              pnMsg.Update;
              lbMsg.Caption := lbMsg.Caption + '...';
              Sleep(2000);
            end
          end)
      end).Start;
  end;
end;
fslejnso

fslejnso1#

您正在将整个辅助过程排队,以便在主线程中运行,而没有为匿名线程留下任何任务。你应该打破逻辑,以便 * 只有 * UI访问与主线程同步,而不是任何非UI工作(即睡眠),例如:

var
  MyThread: TThread;

procedure TFormEscolaImpresso.UpdateMsg(AShow: Boolean; AMsg: string);
begin
  lbMsg.Caption := AMsg;
  pnMsg.Visible := AShow;

  if AShow then
  begin
    MyThread := TThread.CreateAnonymousThread(
      procedure
      begin
        while not TThread.CheckTerminated do
        begin
          TThread.Queue(nil,
            procedure
            begin
              lbMsg.Caption := lbMsg.Caption.Replace('...', '');
            end);
          Sleep(2000);
          if TThread.CheckTerminated then Exit;

          TThread.Queue(nil,
            procedure
            begin
              lbMsg.Caption := lbMsg.Caption + '.';
            end);
          Sleep(2000);
          if TThread.CheckTerminated then Exit;

          TThread.Queue(nil,
            procedure
            begin
              lbMsg.Caption := lbMsg.Caption + '.';
            end);
          Sleep(2000);
          if TThread.CheckTerminated then Exit;

          TThread.Queue(nil,
            procedure
            begin
              lbMsg.Caption := lbMsg.Caption + '.';
            end);
          Sleep(2000);
        end;
      end);
    MyThread.OnTerminate := ThreadTerminated;
    MyThread.Start;
  end else
  begin
    if MyThread <> nil then
      MyThread.Terminate;
  end;
end;

procedure TFormEscolaImpresso.ThreadTerminated(Sender: TObject);
begin
  MyThread := nil;
end;

或者,使用UI计时器定期更新UI,并让工作线程只执行非UI工作,例如:

var
  MyThread: TThread;

procedure TFormEscolaImpresso.UpdateMsg(AShow: Boolean; AMsg: string);
begin
  lbMsg.Caption := AMsg;
  lbMsg.Tag := 0;
  pnMsg.Visible := AShow;
  MyTimer.Enabled := AShow;

  if AShow then
  begin
    MyThread := TThread.CreateAnonymousThread(
      procedure
      begin
        while not TThread.CheckTerminated do
        begin
          for var i := 1 to 4 do
          begin
            Sleep(2000);
            if TThread.CheckTerminated then Exit;
          end;
        end;
      end);
    MyThread.OnTerminate := ThreadTerminated;
    MyThread.Start;
  end else
  begin
    if MyThread <> nil then
      MyThread.Terminate;
  end;
end;

procedure TFormEscolaImpresso.ThreadTerminated(Sender: TObject);
begin
  MyThread := nil;
end;

procedure TFormEscolaImpresso.MyTimerTimer(Sender: TObject);
begin
  if lbMsg.Tag = 3 then
  begin
    lbMsg.Caption := lbMsg.Caption.Replace('...', '');
    lbMsg.Tag := 0;
  end else
  begin
    lbMsg.Caption := lbMsg.Caption + '.';
    lbMsg.Tag := lbMsg.Tag + 1;
  end;
end;

相关问题