我什么时候需要释放应用程序创建的数据模块?

When do I need to free a Data Module created by the Application?

我有如下代码:

begin
  Application.Initialize;
  Application.Title := 'Controle Bancário';
  Application.CreateForm(T_DMEstagio, _DMEstagio);
  Application.CreateForm(T_frmLogin, _frmLogin);
  if (_frmLogin.ShowModal = 1) then
    begin
      FreeAndNil(_frmLogin);
      Application.CreateForm(T_frmPrincipal, _frmPrincipal);
      Application.Run;
    end;
    _DMEstagio.Free;

end.

如果我没有像在代码中那样显式释放 DM,我会得到一个访问冲突异常,但在另一个应用程序中,代码是这样的:

begin
    Application.Initialize;
    Application.Title := ' > Sistema de Gestão Comercial <';
    if HPrevInst = 0 then
    begin
      Application.CreateForm(TFrmPrincipal, FrmPrincipal);
      Application.CreateForm(TIBDM, IBDM);
      Application.Run;
    end ;
end.

我不需要释放 DM,我也没有遇到任何异常。这是为什么?

回答你的问题

"When do I need to free a Data Module created by the Application?"

永远不会。

使用 Application.CreateForm 方法创建的所有数据模块 and/or 表单将由 Application 拥有并自动处理。


不过看来,你的问题与自动销毁过程无关。以下代码应该可以解决您的问题,因为某些组件和 类 需要应用程序完成其完整的 initialization/running 周期才能正常销毁。 RXHook可能就是其中之一。

begin
  Application.Initialize;
  Application.Title := 'Controle Bancário';
  Application.ShowMainForm := false;
  Application.CreateForm(T_DMEstagio, _DMEstagio);
  Application.CreateForm(T_frmLogin, _frmLogin);
  if (_frmLogin.ShowModal = 1) then
    begin
      FreeAndNil(_frmLogin);
      Application.ShowMainForm := true;
      Application.CreateForm(T_frmPrincipal, _frmPrincipal);
    end
  else Application.Terminate;
  Application.Run;
end.

那么上面的代码到底发生了什么?

您正在尝试显示登录表单并根据登录结果继续运行您的应用程序或终止它。

请务必注意,您创建的第一个表格将变为 Application.MainForm,如果该表格在 Application.Run 执行之前发布 Application.MainForm 将被设置回 nil .这将确保下一个创建的表单可以成为主表单。

在您的情况下,这意味着 _frmLogin 将被设置为您的 Application.MainForm。如果登录成功,则释放,_frmPrincipal接管。但是如果登录不成功,执行Application.Run时,_frmLogin仍然是Application.MainForm,会再次显示

这就是 Application.ShowMainForm 发挥作用的地方。当它设置为 false 时,Application.Run 将只是 运行 而不显示任何形式。在您的情况下,它将阻止 _frmLogin 再次出现。当然,在成功登录后,您希望将 Application.ShowMainForm 设置回 true 以确保应用程序正常启动。

在登录不成功的情况下调用 Application.Terminate 将确保您的应用程序退出应用程序主消息循环,该循环将从调用 Application.Run 开始并正常终止。