有一个主窗体,当您单击按钮时,一个框架会加载到窗体中。
按钮代码:
procedure TMain.ButtonObjectsClick(Sender: TObject);
begin
TFrameSystems.Execute(LayoutMain,
procedure(Frame: TFrameSystems)
begin
// DoSomething
end,
procedure(Frame: TFrameSystems; Success: Boolean)
begin
// DoSomething
end);
end;
框架:
...
TKey = class
public
S: string;
constructor Create(const AStr: string);
end;
TFrameSystems = class(TFrameOverlay)
...
private
...
FProcCallback: TProc<TFrameSystems, Boolean>;
FActiveUser: TUser;
procedure UpdateBuildingList;
...
public
constructor Create(AOwner: TComponent); override;
class procedure Execute(AParent: TControl; ProcSet: TProc<TFrameSystems>; ProcExecuted: TProc<TFrameSystems, Boolean>);
property ActiveUser: TUser read FActiveUser write FActiveUser;
...
{ Public declarations }
end;
implementation
uses
...
{$R *.fmx}
class procedure TFrameSystems.Execute(AParent: TControl; ProcSet: TProc<TFrameSystems>;
ProcExecuted: TProc<TFrameSystems, Boolean>);
begin
var Frame := TFrameSystems.Create(AParent);
Frame.Parent := AParent;
Frame.FProcCallback := ProcExecuted;
Frame.Align := TAlignLayout.Contents;
Frame.BringToFront;
if Assigned(ProcSet) then
ProcSet(Frame);
end;
constructor TFrameSystems.Create(AOwner: TComponent);
begin
inherited;
Name := '';
FActiveUser := ClientModule.User;
UpdateBuildingList;
end;
procedure TFrameSystems.UpdateBuildingList;
begin
TThread.CreateAnonymousThread(procedure
var
s1: TStrings;
JSONObject: TJSONObject;
i: integer;
begin
JSONObject := ClientModule.ServerMethodsClient.RefreshUserBuildingList(ActiveUser.id);
ActiveUser.RefreshBuildingList(JSONObject);
s1 := TStringList.Create;
for I := 0 to ActiveUser.BuldingList.Count - 1 do
begin
with cb_object_list.Items do
AddObject(ActiveUser.BuldingList[I].Name, TKey.Create(IntToStr(ActiveUser.BuldingList[I].id)));
s1.AddObject(ActiveUser.BuldingList[I].Kks, TIntObj.Create(ActiveUser.BuldingList[I].id));
end;
Edit1.AssignItems(s1);
end).Start;
end;
当框架打开时,我需要将一些数据上传到组合框。如果您调用 UpdateBuildingList 函数并且在没有线程的情况下执行此操作,那么程序会冻结一段时间。
我尝试通过向该函数添加匿名线程来解决问题,看起来问题已经解决了。但是,为什么它在没有 TThread.Synchronize 的情况下也能工作?总的来说,我通过创建匿名线程做了正确的事情吗?
这里的问题是,您正在从辅助线程逐项填充 ComboBox,这是不允许的,并且可能会导致各种问题。
我还看到您正在使用
AddObject
来将对象添加到每个组合框项目。
您应该以安全的不同方式执行此操作。怎么办?
首先为自己创建一个新的字符串列表,然后使用
AddObject
填充它,就像现在填充组合框一样。您可以在辅助线程中自由地执行此操作。
完成后,只需将 StringList 分配给您的
ComboBox.Items
属性即可。您可以在 Synchronize
内执行此操作,以便在主线程内完成。
这是一个快速代码示例:
//Populate StringList with strings and connected objects
SL := TStringList.Create;
SL.AddObject('Panel1',Panel1);
SL.AddObject('Panel2',Panel2);
//Assign StringList to ComboBox.Items property
//This can be done since TStringList is actually descendant class from
//TStrings which is the property type of ComboBox.Items property
ComboBox1.Items := SL;