4

我有一个包含许多表单的多线程应用程序,但我必须在创建表单之前实例化一些类并调用一些初始化的东西。当然我必须执行相应的终结代码。

这是 .dpr 文件的简化示例:

begin  // .dpr project file
  LoadDlls;
  try
    Config := TConfig.Create;
    try
      Application.Initialize;
      Application.Title := 'Foo';
      Application.CreateForm(TMainForm, MainForm);
      Application.CreateForm(TOtherForm, OtherForm);
      //...other forms...
      Application.Run;
    finally
      Config.Free;
    end;
  finally
    UnloadDlls;
  end;
end;

这里的问题是块内的代码在我的表单的/ sfinally之前执行。看看单元的部分就很清楚了:OnDestroydestructorfinalizationForm

finalization
  if Application <> nil then DoneApplication;

DoneApplication调用Application.DestroyComponents有效地释放了所有Application拥有的表单。

因此,使用创建的表单Application.CreateForm将在主begin..end块内的任何代码之后被销毁。

我想要的是在Application.Run所有表单都被销毁之后,以便它们的OnDestroy事件处理程序可以看到Config我的 dll 中定义的对象和外部函数。如果引发异常,则同上。但我也希望有标准应用程序的异常处理 ifConfig.FreeUnlodDllsraise (应用程序必须仍然存在)。

注意:

  • 我不想使用finalization块(在 .dpr 中是否可能?)以保持代码更清晰和可调试;
  • 目前,我不希望更改太多代码(例如动态创建表单)

我认为最简单的解决方案是显式调用Application.DestroyComponentsafter Application.Run。你觉得有什么缺点吗?有没有更优雅的解决方案?

谢谢

4

2 回答 2

6

实现您想要的最干净的方法是控制表单的破坏。

唯一需要拥有的Application表单是您的主表单。之所以如此,是因为调用创建的第一个表单Application.CreateForm被指定为主表单。因此,我的建议是您应该拨打一个电话,并且只拨打一个电话Application.CreateForm来创建主表单。对于所有其他表单,通过调用它们的构造函数来创建它们。让其他表单归主表单所有。当需要关闭时,销毁主窗体,并让它带走所有拥有的窗体。

您可以像这样编写 .dpr 代码:

begin 
  LoadDlls;
  try
    Config := TConfig.Create;
    try
      Application.Initialize;
      Application.Title := 'Foo';
      Application.CreateForm(TMainForm, MainForm);
      try
        OtherForm := TOtherForm.Create(MainForm);
        YetAnotherForm := TYetAnotherForm.Create(MainForm);
        Application.Run;
      finally
        FreeAndNil(MainForm); 
        // will destroy the other forms since they are owned by the main form
      end;
    finally
      Config.Free;
    end;
  finally
    UnloadDlls;
  end;
end;

要说明的另一点是,您可能不需要卸载 DLL。由于这显然是一个可执行文件,因此系统无论如何都会卸载它们。为什么需要这样做?

于 2013-09-10T15:01:56.643 回答
4

另一种选择是不要让您的表单隐式引用全局配置。通过为每个表单提供对接口
的自己的引用来明确依赖关系。 当引用实例的 RefCount 降至零时(在所有使用它的表单都被销毁之后),它可以自毁。IConfig

使您的表单(和其他对象)对配置的依赖显式将提供其他好处。

  • 测试起来会容易得多。
  • 不需要 IConfig 的表单不会有依赖关系,也不会关心任何一种方式。
  • 因此,这些表单将很容易(并且显然)可移动到具有稍微不同框架的其他应用程序中。
于 2013-09-10T16:10:56.300 回答