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;

ここでの問題は、ブロック内のコードがフォームの/のfinally前に実行されることです。unitのセクションを見ると、これは明らかです。OnDestroydestructorfinalizationForm

finalization
  if Application <> nil then DoneApplication;

そして、所有しているすべてのフォームを効果的に解放するDoneApplication呼び出し。Application.DestroyComponentsApplication

したがって、で作成されたフォームは、メインブロックApplication.CreateForm内のコードの後で破棄されます。begin..end

私が望むのは、Application.Runすべてのフォームが破棄された後、それらのOnDestroyイベント ハンドラーがConfig、DLL で定義されたオブジェクトと外部関数を認識できるようにすることです。例外が発生した場合も同様です。しかし、標準のアプリケーションの例外処理 ifConfig.FreeまたはUnlodDllsraise も必要です (アプリケーションはまだ存在している必要があります)。

ご了承ください:

  • コードをより明確にしてデバッグ可能に保つために、ブロックを使用しないfinalizationことをお勧めします (.dpr で可能でしょうか?)。
  • 今のところ、あまり多くのコードを変更したくない (例: 動的にフォームを作成する)

Application.DestroyComponents最も簡単な解決策は、 afterを明示的に呼び出すことだと思いますApplication.Run。デメリットはあると思いますか?よりエレガントなソリューションはありますか?

ありがとうございました

4

2 に答える 2

4

別のオプションは、フォームが暗黙的にグローバル構成を参照できないようにすることです。
インターフェイスへの独自の参照を各フォームに与えることで、依存関係を明示的にしIConfigます。
参照されたインスタンスの RefCount がゼロになると (それを使用するすべてのフォームが破棄された後)、自己破壊する可能性があります。

フォーム (および他のオブジェクト) の構成への依存関係を明示的にすると、他の利点が得られます。

  • テストがはるかに簡単になります。
  • IConfig を必要としないフォームには依存関係がなく、どちらの方法も気にしません。
  • したがって、これらのフォームは、わずかに異なるフレームワークを持つ他のアプリケーションに簡単に (そして明らかに) 移動できます。
于 2013-09-10T16:10:56.300 に答える