【问题标题】:Is it safe to use Free instead of Release for modal forms in Delphi?在Delphi中使用Free而不是Release作为模态表单是否安全?
【发布时间】:2010-10-29 08:18:27
【问题描述】:

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

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

Free 是销毁模态表单的安全方法吗?正如我在 ShowModal 的源代码中看到的那样,Application.HandleMessage 将被调用,直到 ModalResult 不为 0。这就是 Free 不能干扰挂起的 windows 消息的原因吗?

【问题讨论】:

标签: forms delphi memory-management modal-dialog


【解决方案1】:

是的,在调用ShowModal 之后使用Free 是安全的。

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

【讨论】:

  • 注意不要有任何 Application.ProcessMessages 调用!
  • @GerryColl 为什么?具体在哪里?
  • @Bozzy 如果您使用Release,然后调用Application.ProcessMessagesWM_RELEASE 消息将被处理并释放表单。 Gerry 担心的是,如果您使用 Release 来推迟销毁,然后在实际完成之前意外释放了表单。
【解决方案2】:

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

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

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

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

TMyForm.Create(nil).ShowModal;

而且您不需要专门释放表单,因为它会在完成后自行释放。

【讨论】:

  • 我喜欢这个展示的创造力,但我永远不会使用它,因为问题中显示的代码只是惯用的方式 - 使用您的代码,我总是想知道表单是否被正确释放几个月后绊倒了这个。
  • 嗯,你觉得最好的。但是,这确实完全封装了表单的功能,并减少了您忘记释放它的机会。
  • 将操作设置为 caFree 只需调用 Release。如果你想在 showmodal 之后访问表单的属性,你必须小心,以防某些东西(坏了?)调用 ProcessMessages
  • CM_Release 方法只是调用 Free() 为什么说释放表单不会调用 Release 所做的事件处理程序?
【解决方案3】:

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

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

【讨论】:

  • 小吹牛:Free 也只会在对象不是 nil 时才释放它,第二部分是重要的。
  • 如果 MyForm 是一个局部变量,使用 FreeAndNil() 肯定是矫枉过正。 MyForm.Free 就足够了,实际上 MyForm.Destroy 也可以。
  • +for Allen - 过度使用 FreeAndNil 可以隐藏编译器会发现的错误 - 如果对象可能尚未初始化(通常是条件创建),它不会抱怨。这也没有回答问题(是的,没问题)。
  • 在一个已经被释放的对象上调用 Free 有什么危险吗?如果不是,那么使用 FreeAndNil 也不是“远”更好。如果存在危险,那么 FreeAndNil 在这种情况下实际上也无济于事。 (记住,你释放对象,而不是变量。MyForm 是变量,而不是对象。)
  • 我的假设是 MyForm 是编辑器在首次创建单元时创建的“全局”变量。我同意 Allen 的观点,如果变量完全是本地的,那么 .free 就足够了,因为变量超出了范围。
猜你喜欢
  • 2011-06-05
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
  • 2018-08-17
  • 2023-03-30
  • 1970-01-01
  • 2012-10-03
相关资源
最近更新 更多