Перепроверил 3 раза на андроид.
Первый раз без Sleep:
TTask.Run(procedure
begin
TThread.Synchronize(nil, procedure
begin
FBackgroundLayout.Free; //FBackgroundLayout - родительский элемент
end);
end);
Получил Access violation сразу при нажатии на кнопку.
Второй раз так:
TTask.Run(procedure
begin
Sleep(100);
TThread.Synchronize(nil, procedure
begin
FBackgroundLayout.Free;
end);
end);
При первом нажатии исключений нет, но FBackgroundLayout не удаляется(визуально) и соответственно на кнопку можно нажать ещё раз после чего сразу получаем AV, оно и понятно.
Третий раз, уже основываясь на ваших сообщениях, о том, что нужно везде удалять ссылки, сделал так:
TTask.Run(procedure
begin
Sleep(100);
TThread.Synchronize(nil, procedure
begin
FBackgroundLayout.Parent.RemoveObject(FBackgroundLayout);
FBackgroundLayout.Free;
FBackgroundLayout:= nil;
end);
end);
И теперь все работает.
В моём случае, необходимости удаления подобным образом не было, поскольку ссылки на тот объект я в своём коде не хранил, а потому способ с DisposeOf работал. Но думаю, третий вариант использовать всё же лучше.
UPD. Сделал четвертую проверку, перечитав ваше сообщение ещё раз) . Убрал поток:
FBackgroundLayout.Parent.RemoveObject(FBackgroundLayout);
FBackgroundLayout.Free;
FBackgroundLayout:= nil;
//Ну или FreeAndNil(FBackgroundLayout)
И оно заработало! И без каких-либо ошибок.
UPD 2. Теперь точно всё) Я вспомнил зачем создавал поток и ставил Sleep. Дело в том, что в Windows приложении, если при нажатии на кнопку удалить его сразу, то не будет сообщения о том, что произошло "MouseUp" кнопки, в связи с чем, рамки приложения (т.е. кнопки сворачивание, закрыть и т.д.) не реагируют на нажатия мыши до того, пока не нажмете на "нажимаемый" элемент в самом приложении. И потому 4 вариант не подходит для Windows приложений.