実際、私はこのコードを使用していて問題なく動作しますが、正しい方法であるかどうか疑問に思っています。
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
実際、私はこのコードを使用していて問題なく動作しますが、正しい方法であるかどうか疑問に思っています。
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
WaitFor()
VCL TThreadクラスには、メインスレッドコンテキスト内で呼び出されたときにメインメッセージキューを内部的にポンプする独自のメソッドがあります。
MyThread.WaitFor;
ShowMessage('i am done');
呼び出しApplication.ProcessMessages
は、一般的にコードの匂いと見なされます。何もすることがない場合は、メイン スレッドをアイドル状態にします。
あなたが会社を経営していて、従業員の 1 人が店に走って行き、非常に必要な物資を手に入れる必要がある場合、あなたは彼が戻ってくるまでドアのそばを歩きますか、それともオフィスに座って休んで待つことを好みますか?彼がドアを通り抜けるのが聞こえたので、物資がここにあることがわかりましたか?いずれにせよ、彼は同じくらいの時間を費やすでしょうが、最初の方法はあなたの足を疲れさせます.
同様に、UI がスレッドを監視する代わりに、スレッドが UI に報告するようにします。これを行う 1 つの方法は、スレッドを使用PostMessage
して、スレッドが終了したときにそれを起動したフォームにカスタム メッセージを送信し、それに応答するメッセージ ハンドラーをフォームに配置することです。
それは正しいように見えます(正しい場合は、それが機能することを意味します)。私が変更したいのは、CPU を消費せずにもう少し待つことです (アプリケーションの応答性を維持するには 50 ミリ秒が適切です)。
while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
確かに他にも方法はあります...<冗談>ですが、私は通常、主要なエンジニアリング原則の 1 つを適用します。
機能する場合は、触れないでください。</冗談>
私は Mason Wheeler の発言に同意します。メイン スレッドにその仕事を任せるのが最善ですが、スレッドで OnTerminate イベントを使用することをお勧めします。これはより「Delphi 自然」であり、内部ロジックが PostMessage ビットを処理します。TThread はコンポーネントではないため、オブジェクト インスペクターで表示することはできず、自分でイベント ハンドラーを作成してアタッチする必要があります。スレッドが完了/終了した後に(メインスレッドで!)呼び出されます。
問題ないように見えますが、jachguateのように、0 よりも大きなタイムアウト値も使用します。を使用するWaitForSingleObject(MyThread.Handle, 100)
と、メイン スレッドはもう少し長く待機するため、消費する CPU サイクルが少なくなります。
ただし、より良い解決策はメッセージを使用することです。アプリケーションはスレッドを開始し、すべてのコントロールを無効モードにします。次にスレッドが実行され、終了したら、メイン ウィンドウに対してSendMessageまたはPostMessageを使用して、スレッドが再度実行されたことを通知します。次に、アプリケーションはすべてのコントロール (およびその他のもの) を再び有効にします。これには、このソリューションで独自のメッセージループを実行する代わりに、アプリケーションの「自然な」メッセージループを有効に保つという利点があります。
残念ながら、メッセージ方式には欠点が 1 つあります。スレッドがクラッシュした場合、メッセージが返されないため、バックアップ計画が実用的です。たとえば、スレッドがまだ生きているかどうかを毎秒チェックするタイマー コントロールをメインフォームに追加します。そうでない場合は、フォームを再度アクティブにして、それ自体を再び無効にします。