我有当前的情况,我使用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 线程正在工作,我对禁用表单所做的交互被发送到队列,一旦线程完成,它们都会被发送回表单。
我的问题是:是否可以实际禁用表单,当我说禁用时,我的意思是阻止所有消息,直到我手动允许可以再次开始接受的某个点?
提前谢谢。