Перейти к содержанию
Fire Monkey от А до Я
  • 0

Динамическое удаление объектов и форм (опять...)


gonzales

Вопрос

Доброго времени суток!

Знаю, что тема поднималась 100500 раз, сам писал в них, но тем не менее...

После перехода на 10.4 стал замечать, что приложение  на мобильных платформах стало частенько зависать или выдавать сообщения External Exception xx. Стал разбираться и заметил, что такое поведение часто происходит после уничтожения объектов или форм. Прогуглив тему динамического удаления объектов нашел информацию вот такого характера

Now, that being said, in RAD Studio 10.4, Embarcadero has removed object ARC handling completely, going back to the traditional memory management model (which they now refer to as "Unified Memory Management"). In which case, TObject.Free() and FreeAndNil() now behave the same as they always have on non-mobile platforms, but now on all platforms equally. So your original code will now work as expected, you do not need to switch to TObject.DisposeOf() in 10.4 onwards (though, you can if you want to, it will behave exactly like TObject.Free(), and give you the desired effect if you need to support 10.3 and earlier). 

То есть, если я правильно понимаю, Эмба отказалась от ARC и вернулась к традиционной модели управления памятью. И теперь нужно обратно вернуться к TObject.Free(), еще компилятор стал ругаться, что метод Release помечен, как deprecated - то есть в скором времени исчезнет. В связи с этим два вопроса 

1. Может ли конструкция r.DisposeOff; r:=nill; приводить к зависанию программы? Нужно ли теперь заменить все на r.Free; 

2. Как теперь удалить форму, кликнув на кнопку, которая расположена на этой форме? 

procedure TForm30.BlackRectClick(Sender: TObject);
begin
  form1.BlackRect.Visible := false;
  Form30.Close;
  //Form30.Free;
  Form30.Release;
end;

Такая конструкция работает, но часто программа зависает

procedure TForm30.BlackRectClick(Sender: TObject);
begin
  form1.BlackRect.Visible := false;
  Form30.Close;
  Form30.Free;
  //Form30.Release;
end;

Такая конструкция крашит программу, но это и понятно, удаляем сук, на котором сидим. Но если Release перестанет работать, как тогда удалить форму?

Ссылка на комментарий

Рекомендуемые сообщения

  • 1

посмотрите реализацию Release и сделайте точно так же как там... но с формой не советую...

в случае с формой вызывайте Close  а на событие OnClose укажите CloseAction = caFree тогда форма разрушится корректно... должна, сам не проверял, но судя по коду в исходниках все должно быть хорошо...

Ссылка на комментарий
  • 0

Если вы удаляете объект в обработчике этого объекта, будьте готовы, что при выходе из обработчика программа вполне может обратиться к уже несуществующему объекту

Естественно, вы получите AV

Лучший выход IMHO 

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.ForceQueue(nil, 
    procedure begin
      ???.Free;
    end);
end;

обращаю внимание, что никакого FreeAndNil(Form1) не предполагается.

потому что по-прежнему, что в D1, что в D10 обращаться из класса к экземпляру этого класса, это моветон и ошибка архитектуры

Нужно придумывать что-то еще. поэтому и ??? поставил

если хотите иметь какие-то глобальные ссылки на форму, значит, стоит делать какой-то менеджер этих форм и удалять через его методы. 

но если прямо просто побыстрогнокодить то конечно FreeAndNil(Form1) работать будет. Без ошибок.

Изменено пользователем krapotkin
Ссылка на комментарий
  • 0
В 15.11.2020 в 17:01, krapotkin сказал:

Лучший выход IMHO

Тоже остановился на этом варианте.

 

В 12.11.2020 в 19:21, slav_z сказал:

в случае с формой вызывайте Close  а на событие OnClose укажите CloseAction = caFree тогда форма разрушится корректно... должна, сам не проверял, но судя по коду в исходниках все должно быть хорошо...

Пробовал и такой вариант - почему-то иногда падает приложение. Не разобрался, почему.

В 12.11.2020 в 19:35, Android сказал:

на 10.4 делаю r.Release; r:=nil;

Перешел на r.Free. Вроде все корректно

Ссылка на комментарий
  • 0
В 15.11.2020 в 17:01, krapotkin сказал:

Нужно придумывать что-то еще. поэтому и ??? поставил

Ничего лучше Form1.Free - я не придумал. Но работает без сбоев.

Уважаемый krapotkin, не могли бы Вы пояснить более развернуто Вашу мысль. Я во многих ваших ответах встречаю, что обращаться из класса к экземпляру класса - это плохо. Но не понятно, почему, что плохого произойдет при таком обращении?

Например вот такой код

procedure TForm2.Button2Click(Sender: TObject);
begin
form2.button2.text:='test';
end;

Вы везде указываете, что такая запись некорректная и правильно было бы писать button2.text:='test'; 

Ссылка на комментарий
  • 0

Ну в целом это общий момент. Класс это чертежи автомобиля, а объект это сам автомобиль, сделанный по этому чертежу. Понятно, что если вы делаете всегда только одну машину, вы можете к ней обращаться прямо из чертежа. Но вы же понимаете, что это неверно? 

Ссылка на комментарий
  • 0

 Правильно ли я Вас понял, Вы имеете в виду, что если у меня будет несколько объектов типа TForm2 - то далеко не факт, что экземпляр form2 вообще существует. Но поскольку этот экземпляр - единственный, то такой подход применим.

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...