There is a main form, when you click on the button, a frame is loaded into the form.
Button code:
procedure TMain.ButtonObjectsClick(Sender: TObject);
begin
TFrameSystems.Execute(LayoutMain,
procedure(Frame: TFrameSystems)
begin
// DoSomething
end,
procedure(Frame: TFrameSystems; Success: Boolean)
begin
// DoSomething
end);
end;
Frame:
...
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;
When the frame opens, I need to upload some data to the combobox. If you call the UpdateBuildingList function and do it without a thread, then the program freezes for a while.
I tried to solve the problem by adding an anonymous thread to this function and it seems like the problem is solved. However, why does it work without TThread.Synchronize and in general, did I do the right thing by creating an anonymous thread?
The problem here is that you are populating your ComboBox from secondary thread item by item which is not allowed and could lead to various problems.
I also see you are using AddObject
in order to add object to each ComboBox item.
You should do this in a different way that is tread safe. How?
First create yourself a new string list and populate it using AddObject
like you populate your combo box now. You can freely do this in secondary thread.
Once you have done that simply assign your StringList to your ComboBox.Items
property. You do this within Synchronize
so that it is done within main thread.
Here is a quick code example:
//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;