0

我有当前的情况,我使用omnithreadlibrary 进行一些通用的后台工作,如下所示:

TMethod = procedure of object;

TThreadExecuter = class;

IPresentationAnimation = interface
  ['{57DB6925-5A8B-4B2B-9CDD-0D45AA645592}']
  procedure IsBusy();
  procedure IsAvaliable();
end;

procedure TThreadExecuter.Execute(AMethod: TMethod); overload;
var ATask : IOmniTaskControl;
begin
  ATask := CreateTask(
    procedure(const ATask : IOmniTask) begin AMethod(); end
  ).OnTerminated(
    procedure begin ATask := nil; end
  ).Unobserved().Run();

  while Assigned(ATask) do
    begin
      Sleep(10);
      Application.ProcessMessages;
    end;
end;

procedure TThreadExecuter.Execute(ASender: TCustomForm; AMethod: TMethod); overload;
var AAnimator : IPresentationAnimation;
begin
  if(Assigned(ASender)) then
    begin
      TInterfaceConsolidation.Implements(ASender, IPresentationAnimation, AAnimator, False);
      if(Assigned(AAnimator)) then AAnimator.IsBusy()
      else ASender.Enabled := False;
    end;
  try
    Self.Execute(AMethod);
  finally
    if(Assigned(ASender)) then
      begin
        if(Assigned(AAnimator)) then AAnimator.IsAvaliable()
        else ASender.Enabled := True;
      end;
  end;
end;

所以在我开始执行之前,我会像这样阻止界面:

TMyForm = class(TForm, IPresentationAnimation);

procedure TMyForm.LoadData();
begin
  TThreadExecuter.Execute(Self, Self.List);
end;

procedure TMyForm.IsBusy();
begin
  try
    Self.FWorker := TPresentationFormWorker.Create(Self);
    Self.FWorker.Parent := Self;
    Self.FWorker.Show();
  finally
    Self.Enabled := False;
  end;
end;

当线程完成时,我像这样释放块:

procedure TMyForm.IsAvaliable();
begin
  try
    Self.FWorker.Release();
  finally
    Self.Enabled := True;
  end;
end;

注意:TPresentationFormWorker 是一个动画表单,我把它放在忙碌的表单中。

问题是,当表单“忙”执行线程时,即使我禁用它,我仍然可以与他交互,例如:

  • 我可以点击任何按钮,当线程完成执行时,按钮的动作被触发;
  • 我可以输入任何控件,例如编辑一些无意义的信息,当线程完成执行时,我提供给控件的内容将被擦除回之前(ui rollback?lol);

所以我的猜测是,由于 application.processmessages 线程正在工作,我对禁用表单所做的交互被发送到队列,一旦线程完成,它们都会被发送回表单。

我的问题是:是否可以实际禁用表单,当我说禁用时,我的意思是阻止所有消息,直到我手动允许可以再次开始接受的某个点?

提前谢谢。

4

0 回答 0