在Delphi中使用Free而不是Release for modal表单是否安全?

mjn*_*mjn 13 forms delphi memory-management modal-dialog

Delphi在线帮助说,Release应该用于从内存中删除表单.但是,在模态形式的许多例子中,我看到了这个结构:

MyForm := TMyForm.Create(nil);
try
  MyForm.ShowModal;
finally
  MyForm.Free;
end;
Run Code Online (Sandbox Code Playgroud)

免费是一种破坏模态形式的安全方式吗?正如我在ShowModal的源代码中看到的那样,将调用Application.HandleMessage,直到ModalResult不为0.这就是为什么Free不能干扰挂起的Windows消息的原因?

Zoë*_*son 17

是的,通话Free后可以安全使用ShowModal.

您需要使用的情况Release是当您处于事件处理程序(例如OnClick)的中间时,事件之后的进一步处理将必须访问该表单.在这种情况下,调用Release会发布一条CM_RELEASE消息,该消息不会释放事件,直到事件处理程序完成并且控制已返回到消息泵(ProcessMessages/ Application.Run). ShowModal在事件处理程序完成并且控制使其备份到堆栈之前不会返回,因此Free之后的调用实际上与CM_RELEASE处理消息的位置相同.

  • 并注意不要有任何Application.ProcessMessages调用! (2认同)

Tim*_*van 6

这取决于.Free表单不会调用事件处理程序,Release并且不会处理可能已发布到表单并排队的任何消息.因此,虽然在很多情况下Free(或者说大多数情况下)调用(或FreeAndNil)可以正常工作,但由于看似随机的原因,可能会导致一些非常奇怪的行为.

我建议的替代方案是在OnClose事件中将Action设置为caFree,如下所示:

procedure FormClose(Sender : TObject; Action : TCloseAction)
begin
  Action := caFree;
end;
Run Code Online (Sandbox Code Playgroud)

然后你可以编写如下代码:

TMyForm.Create(nil).ShowModal;
Run Code Online (Sandbox Code Playgroud)

而且你不需要特别释放表单,因为它会在完成后自由释放.

  • 嗯,你觉得什么都是最好的。但是,这确实完全封装了表单的功能,并减少了忘记释放它的机会。 (2认同)

ska*_*adt 5

绝对可以,您也可以使用 FreeAndNil 例程。FreeAndNil 例程只会在对象尚未为 nil 时才释放该对象,并在释放后将其设置为 nil。如果你直接在一个已经被释放的对象上调用 free,你会得到一个访问冲突。

MyForm := TMyForm.Create(nil); 
try 
  MyForm.ShowModal; 
finally 
  FreeAndNil(MyForm); 
end;
Run Code Online (Sandbox Code Playgroud)

  • 小挑剔:Free 也只会释放尚未为零的对象,第二部分是重要的部分。 (5认同)
  • 如果 MyForm 是一个局部变量,那么使用 FreeAndNil() 肯定是矫枉过正。MyForm.Free 就足够了,事实上 MyForm.Destroy 也能工作。 (3认同)