1)「オリジナルのDelphi」の方法であり、同期されたメソッドが実行されるまでバックグラウンドスレッドを強制的に待機させ、システムを私が満足しているよりも多くのデッドロックの可能性にさらします。TThread.Synchronizeは少なくとも2回書き直されました。D3で一度使用しましたが、問題がありました。私はそれがどのように機能するかを見ました。二度と使用しませんでした。
2)私が最もよく使うデザインです。私はapp-lifetimeスレッド(またはスレッドプール)を使用し、スレッド間通信オブジェクトを作成し、TObjectQueueの子孫に基づく生産者/消費者キューを使用してそれらをバックグラウンドスレッドにキューイングします。バックグラウンドスレッドはオブジェクトのデータ/メソッドを操作し、結果をオブジェクトに格納し、完了すると、オブジェクトをPostMessage()(lParamにキャスト)してメインスレッドに戻し、結果をメッセージでGUI表示します-ハンドラー(lParamを再度キャストします)。メインGUIスレッドのバックグラウンドスレッドは、同じオブジェクトを操作する必要はなく、相互のフィールドに直接アクセスする必要もありません。
私は、GUIスレッド(RegisterWindowClassとCreateWindowで作成)の非表示ウィンドウを、PostMessageのバックグラウンドスレッド、LParamのcommsオブジェクト、およびWParamとしての「ターゲット」TwinControl(通常はTFormクラス)に使用します。非表示ウィンドウの簡単なwndprocは、TwinControl.Perform()を使用して、LParamをフォームのメッセージハンドラーに渡します。これは、オブジェクトをTForm.handleに直接PostMessagingするよりも安全です。残念ながら、ウィンドウが再作成されると、ハンドルが変更される可能性があります。非表示のウィンドウがRecreateWindow()を呼び出すことはないため、そのハンドルは変更されません。
生産者/消費者キュー'GUIから'、スレッド間通信クラス/オブジェクトおよびPostMessage()'GUIへ'はうまく機能します-私は何十年もそれをやっています。
commsオブジェクトの再利用もかなり簡単です-起動時にループでロードを作成し(できれば、commsオブジェクトがすべてのフォームよりも長持ちするように初期化セクションで)、それらをPCキューにプッシュします-それがプールです。commsクラスにプールインスタンスのプライベートフィールドがある場合は簡単です。'releaseBackToPool'メソッドはパラメーターを必要とせず、複数のプールがある場合は、オブジェクトが常に独自のプールに解放されるようにします。
3)DavidHeffermanのコメントを実際に改善することはできません。ただそれをしないでください。