Form.Release + NIL

11

如果在使用表单后调用Form.Release,则会释放所有相关内存但不将表单变量设置为nil。

if not assigned (Form1) then
  begin
    Application.CreateForm(Tform1, Form1);
    try
      // Do something
    finally
      Form1.Release
    end;
  end;
为了能再次调用相同的代码,必须在某个时候将Form1设置为nil。从Release的描述中我无法做到这一点。
Form1 := nil;

在释放之后,因为释放过程会在调用后直接返回,而在窗体实际释放之前。我无法检测Form.Release何时完成以将窗体变量设置为nil。

最好的方法是什么?


相关链接:https://dev59.com/1HNA5IYBdhLWcg3wjOlS - Gabriel
小心使用Application.CreateForm方法。使用该方法创建的第一个窗体将被设置为主窗体。因此,请确保首先将其用于您的主窗体。之后,您也可以在其他窗体上使用它。 - Gabriel
5个回答

17

添加这一行代码

  Form1 := nil;  

在调用Release之后。

Release只是向窗体发布一个CM_RELEASE消息,允许窗体在处理CM_RELEASE消息之前完成其队列中的任务(事件处理程序),这通常意味着只需调用Free。
因此,在调用Release之后,您不应假定Form变量仍指向有效的窗体,因此将nil放入变量中。


11
释放只是一个(可能)延迟的释放。在调用释放后,第一件事情就是将变量置空。 这样,即使某些代码在实际销毁 Form1 之前尝试引用它,您也会很安全。在像您代码中的情况下,它将安全地为新使用创建另一个 Form1,而不会打扰正在被销毁的那个 Form1。

4

你可以始终调用这个函数:

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;

在将对象转换为 TObject 后,请务必检查类型,因为您无法测试 Obj 的类型。这样做应该是安全的,因为像 Free 一样,Release 是非虚拟的。


2
正如所述,释放(Release)仅是一个延迟的自由,用于关闭/释放自身。除了被推迟外,它与Release没有任何不同。因此,在该示例中调用Release没有用处。调用Free似乎更合理。在调用Free之后,您可以将其设置为nil或使用FreeAndNil。如果您仍然想使用Release,那也没问题。只需将变量值设置为nil即可。这样做并不会使论坛行为有所不同。但请记住,在这种情况下,调用Free比调用Release更有效率和更具确定性。我的偏好是只在真正需要时使用Release。

1
在 Delphi Win32 中,释放对象的适当方式是调用 。
FreeAndNil(Form1)

这个函数可以在单个调用中完成两个任务。

然而,我有一种隐约的感觉,你的问题并不止于此。你是在使用Delphi for .NET吗?如果是,那么是哪个版本呢?


Roddy,我正在使用Delphi Win32(抱歉没有提到)。据我所知,对于一个窗体,Release执行的任务比简单的FreeAndNil要多得多,后者无法释放由该窗体拥有的组件。这是正确的吗? - Holgerwa
是的,Release 做了更多的事情,但只是为了推迟 Free 的调用。您不需要调用已推迟的 Free,因此您不需要调用 Release,可以直接调用 Free。另请参见 https://dev59.com/cnVC5IYBdhLWcg3wfxQ8。 - Lars Truijens

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