【发布时间】:2021-01-14 10:52:22
【问题描述】:
我的 FireMonkey 应用有一个保存按钮:
procedure TFormProductionRuns.buSaveFinishProductClick(Sender: TObject);
begin
ShowActivity;
ITask(TTask.Create(
procedure
begin
try
TThread.Synchronize(nil,
procedure
begin
PostFinishProduct;
end);
finally
TThread.Synchronize(nil,
procedure
begin
HideActivity;
end);
end;
end)).Start;
end;
活动方法定义为:
procedure TFormProductionRuns.ShowActivity;
begin
frProgress1.ShowActivity;
end;
procedure TFormProductionRuns.HideActivity;
begin
frProgress1.HideActivity;
end;
procedure TfrProgress.ShowActivity;
begin
Self.Visible := True;
ProgFloatAnimation.Enabled := True;
end;
procedure TfrProgress.HideActivity;
begin
ProgFloatAnimation.Enabled := False;
Self.Visible := False;
end;
框架设置为对齐内容,因此可见时会填满整个应用屏幕,并包含“忙碌”动画。大部分工作是对 post web 方法的 REST 请求。
procedure TFormProductionRuns.PostFinishProduct;
var
AList: TObjectList<TFinishedProduct>;
sReqBody, sResponse: String;
begin
...
sReqBody := TJSONUtils.ObjectsToJSONArray<TFinishedProduct>(AList).ToString;
RESTReqPostTransaction.Params.ParameterByName('ReqBody').Value := sReqBody;
RESTClient1.Params.ParameterByName('host_port').Value := FLoginInfo.Server + ':' + FLoginInfo.Port;
HTTPBasicAuthenticator1.Username := FLoginInfo.LoginId;
HTTPBasicAuthenticator1.Password := FLoginInfo.LoginPw;
try
RESTReqPostTransaction.Execute;
except on E:Exception do
begin
ShowMessage('Post Finish Product failed. Exception: ' + E.Message);
Exit;
end;
end;
sResponse := RESTResponseFromPost.Content;
...
end;
我发现动画在处理此请求时停止,但我的理解是主线程会在工作线程等待响应时继续。
该应用确实有一个类似的方法,它使用 Get REST 请求而不是 Post,并且在工作线程运行时为“忙碌”图形设置动画没有问题等待回复。
【问题讨论】:
-
在调用周围使用 Synchronize 意味着您最好不要使用线程。只有在工作完成后有必要时才进行同步以将结果传回。
-
TTask在主线程中完成所有工作,因此动画当然会被阻止。不要使用Synchronize()运行TTask的操作。仅在访问共享资源、UI 控件等或将通知/更新发送回主线程时使用它(在后一种情况下,请考虑改用TThread.Queue())。 -
感谢 cmets 和回答。我所做的编码是基于 Embarcadero 提供的医疗保健行业模板 FireMonkey 项目。我将研究以不同的方式实现该过程,我仍然希望等待 REST 请求完成,然后再允许用户执行任何其他操作,但我不想阻止主线程执行动画。跨度>
标签: multithreading rest delphi firemonkey