Вопрос

если после использования формы вызывается Form.Release, он освобождает всю связанную память, но не устанавливает для переменной формы значение nil.

if not assigned (Form1) then
  begin
    Application.CreateForm(Tform1, Form1);
    try
      // Do something
    finally
      Form1.Release
    end;
  end;

Чтобы снова вызывать тот же код, в какой-то момент для Form1 должно быть установлено значение nil. Из описания релиза я не могу сделать

Form1 := nil;

сразу после Release, поскольку процедура Release будет возвращаться сразу после вызова и до того, как форма будет фактически освобождена. Я не могу определить, когда завершается Form.Release, чтобы установить для формы var значение nil.

Каков наилучший способ сделать это?

Это было полезно?

Решение

Поместите строку

  Form1 := nil;  

сразу после звонка в Release.

Release просто отправляет сообщение CM_RELEASE в форму, что позволяет форме завершать то, что находится в ее очереди (обработчики событий), до обработки сообщения CM_RELEASE, что обычно означает просто вызов Free.
Таким образом, после вызова Release не следует предполагать, что переменная Form все еще указывает на допустимую форму, тем самым помещая nil в переменную.

Другие советы

Релиз - это просто (потенциально) отложенный бесплатный. Первое, что вы должны сделать после вызова Release, - обнулить переменную.
Тогда вы будете в безопасности, даже если какой-то код попытается обратиться к Form1 до того, как он будет фактически уничтожен. В случае, как в вашем коде, он просто безопасно воссоздает другую форму Form1 для нового использования, не беспокоясь об уничтожаемой.

Из вас всегда можно было так назвать:

procedure FreeOrReleaseAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  if Temp is TCustomForm then
    TCustomForm(Temp).Release
  else
    Temp.Free;
end;

Обязательно проверьте тип после приведения к объекту TO, поскольку вы не можете проверить тип Obj. Это должно быть безопасным, поскольку, как и Free, Release не является виртуальным.

Как уже упоминалось, Release является только отложенным Free для формы, которую можно использовать, если она хочет закрыть / освободить себя. Кроме того, отсрочка не отличается от Release. Таким образом, нет смысла вызывать Release в этом примере. Вызов Free кажется более логичным. И вы можете установить его на ноль после вызова Free или использовать FreeAndNil.

Если вы все еще хотите использовать Release, это нормально. Просто установка значения переменной на ноль работает. Это не заставляет форум вести себя по-другому. Но помните, что в этом случае более эффективно и более детерминировано называть Free вместо Release. Я предпочитаю использовать Release только там, где это действительно необходимо.

В Delphi Win32 подходящим способом освобождения объектов является вызов

FreeAndNil(Form1)

Это выполняет обе работы за один вызов.

Тем не менее, у меня есть подлое ощущение, что в твоем вопросе есть нечто большее, чем кажется на первый взгляд. Используете ли вы Delphi для .NET - и если да, то какая версия?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top