Delphi: 表单自我释放是否可行?

17
我有一个表单,用于显示一些信息几秒钟。表单自己释放是否可以?我能在构造函数中启动一个计时器,然后在计时器事件中调用self.free吗?这样做会不会潜在地导致问题?

根据手册,在事件处理程序内,您必须调用 Release 而非 Close 或 Free。https://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Forms.TCustomForm.Release - Gabriel
4个回答

31

此外,你可以使用表单调用 Release

它会向表单发送一个 CM_RELEASE 消息。随着反应,它会调用 Free。 释放的优点在于,不会留下可能导致崩溃的表单消息。


我认为我会选择这个选项,再加上将所有者设置为额外的保险。 - Vegar
@Rigel,不完全正确。Close使用CloseQuery可以用于中断进程,并不能保证释放表格。根据关闭操作,该窗体还可能会隐藏或最小化(请查看Vcl.Forms.pas中的TCustomForm.Close)。 - Toon Krijthe
当然。Close将根据您设置的关闭操作来关闭表单,但我说的是其他事情:(如果设置为caFree).Close.Release一样安全。我的意思是它不会像.Free那样创建问题。 - Gabriel

18

您可以使表单在被用户或代码关闭时自动释放:

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

procedure TForm27.FormCreate(Sender: TObject);
begin
  Timer1.Enabled := True;
end;

procedure TForm27.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  Close;
end;

构造函数中一定要提供一个所有者,以防应用程序关闭时窗体尚未被销毁。所有者将在释放自身之前先释放窗体。


我越想越喜欢TCloseAction的想法。也许我应该使用它来代替release... - Vegar
3
如果表单有DefaultCloseAction属性,那么就可以自动释放它们而不需要分配事件处理程序。 - Arioch 'The

1

我有一整套自我释放的对象,我已经运行了各种测试,并没有显示任何问题/泄漏。一个TForm可能更复杂,但只要Self.Free()是最后一次调用,你就应该是安全的。

(对于那些想知道为什么我有自我释放的对象的人; 我经常在系统中传递它们,所以我实现了自己的引用计数方案。当最后一个引用被释放时,对象就会自我释放)。


但是Self.Free几乎永远不会是一个表单调用的最后一次操作,因为一个表单几乎总是在响应某些用户操作时运行代码。请使用Release。 - Rob Kennedy
为什么不使用接口来进行引用计数? - Mason Wheeler

0

这正是接口所做的。


1
是的,但你应该记住 Delphi 的 TComponent 会覆盖接口的引用计数,这经常会导致混淆。 - Fabio Gomes
使用接口时,窗体将在其作用域之外被释放。我不想要那样。我希望它能够自由地存在,直到没有任何对它的引用,然后在完成显示后自我释放。 - Vegar
Fabio:我相信你可以覆盖它。 Vegar:接口是引用计数的,而不是范围管理的。 - Arafangion
是的,但只要您不保留引用,当创建表单的代码超出范围时,引用计数就会降为零吗? - Vegar
只有当你不将它传递给其他东西时... 当你创建对象时,引用计数会增加,因此为1。当你将其分配给其他东西时,它再次增加,因此为2。当它离开作用域时,它会被减少到1,并因此不会被销毁。 - Arafangion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接