Безопасно ли использовать Free вместо Release для модальных форм в Delphi? - PullRequest
12 голосов
/ 27 мая 2009

В онлайн-справке Delphi говорится, что Release следует использовать для удаления формы из памяти. Однако во многих примерах для модальных форм я видел эту конструкцию:

MyForm := TMyForm.Create(nil);
try
  MyForm.ShowModal;
finally
  MyForm.Free;
end;

Является ли Free безопасным способом уничтожить модальную форму? Как я вижу в источнике для ShowModal, Application.HandleMessage будет вызываться до тех пор, пока значение ModalResult не станет равным 0. Является ли это причиной того, что Free не может вмешиваться в ожидающие сообщения Windows?

Ответы [ 3 ]

17 голосов
/ 27 мая 2009

Да, безопасно использовать Free после ShowModal вызова.

Случаи, когда вам нужно использовать Release, это случаи, когда вы находитесь в середине обработчика события (например, OnClick), когда дальнейшая обработка после события должна будет получить доступ к форме. В этом случае вызов Release вместо этого отправляет сообщение CM_RELEASE, которое не освобождает событие до тех пор, пока не будет обработан обработчик событий и управление не вернется к насосу сообщений (ProcessMessages / Application.Run). ShowModal не возвращается до тех пор, пока обработчик события не будет завершен, и управление не сделает его резервную копию стека, поэтому последующий вызов Free фактически является тем же местом, где в противном случае обрабатывалось бы сообщение CM_RELEASE.

5 голосов
/ 27 мая 2009

Это зависит. Free при заполнении формы не вызывают обработчики событий, которые Release делает, и любые сообщения, которые могли быть отправлены в форму и помещены в очередь, не будут обрабатываться. Поэтому, хотя во многих и, возможно, в большинстве случаев вызов Free (или FreeAndNil) будет работать нормально, это может привести к очень странному поведению по казалось бы случайным причинам.

Альтернативой, которую я бы предложил, является событие OnClose, устанавливающее для Action значение caFree, например:

procedure FormClose(Sender : TObject; Action : TCloseAction)
begin
  Action := caFree;
end;

Затем вы можете написать код так:

TMyForm.Create(nil).ShowModal;

И вам не нужно специально освобождать форму, так как она освободится сама по себе.

4 голосов
/ 27 мая 2009

Абсолютно, и вы также можете использовать процедуру FreeAndNil. Процедура FreeAndNil освобождает объект, только если он еще не равен нулю, а также устанавливает его равным нулю после освобождения. Если вы вызываете free непосредственно для объекта, который уже был освобожден, вы получаете нарушение прав доступа.

MyForm := TMyForm.Create(nil); 
try 
  MyForm.ShowModal; 
finally 
  FreeAndNil(MyForm); 
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...