我可以保证在表单销毁后执行自定义终结代码吗?

yan*_*kee 4 delphi exception-handling finalization delphi-7

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

这是.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;
Run Code Online (Sandbox Code Playgroud)

这里的问题是finally块内部的代码在我的表单的OnDestroy/ destructors 之前执行.这清楚地看着单位finalization部分Form:

finalization
  if Application <> nil then DoneApplication;
Run Code Online (Sandbox Code Playgroud)

并且DoneApplication呼叫Application.DestroyComponents有效地释放所有Application拥有的形式.

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

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

注意:

  • 我宁愿不使用finalization块(可能在.dpr中?)来保持代码更清晰和可调试;
  • 现在,我不想改变太多代码(例如动态创建表单)

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

谢谢

Dav*_*nan 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;
Run Code Online (Sandbox Code Playgroud)

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