2012-04-26 15 views
1

アプリケーション全体を使用できるProcessMessagesの使用が合法であるかどうかを知る必要があります。ProcessMessagesとアプリケーションの使用

擬似コード:

メインスレッドボタンコール検索。

procedure ButtonOnClick; 
begin 
    var1 = ExecuteSearch(); 
end;  

function ExecuteSearch:Something; 
begin 
thread.StartThread; 
while thread.Finished do 
Application.ProcessMessages; 
result := something; 
end; 

私はこのような構成を使用する場合、私は私のソフトウェアの他の部分をクリックして、それを使用することができます。しかし、私はこれがどのように機能するのか分かりません。安全であれば

+0

純粋に安全です。あなたは、スレッドがスタックしないことを確認する必要があります。もしそうなら、メインプログラムは機能するでしょうが、あなたはプログラム –

+2

を終了することができません。while thread.Finished'? –

+2

GUIイベントハンドラで待機しないでください。 –

答えて

2

コードは安全ですが、開始するスレッドでOnTerminateイベントを使用することもできます。この方法で、Delphiがバックグラウンドスレッドからメインスレッドにポストバックする方法を制御させることができます。内部的には、スレッドのSynchronizeメソッドを使用します。このメソッドは、スレッドが中間の進行状況情報をメインスレッドにポストするために使用できます。

+0

私はこのトピックについて読むことができるので、それが安全かどうかわかりますか? – userbb

+0

もっと詳しく読む:http://docwiki.embarcadero.com/Libraries/en/System.Classes.TThread.Synchronize and here http://docwiki.embarcadero.com/Libraries/en/System.Classes.TThread.OnTerminate –

2

これは安全にすることができますが、あなたは火事で遊んでいます。あなたは再入国の危険があります。ユーザーがボタンをもう一度押すことができないようにする必要があります。私はあなたが検索を実行している間、それを無効にしていると信じています。最初にProcessMessagesを呼び出す前に、無効になっていることを確認する必要があります。

私の助言は、常にProcessMessagesの使用を避けることです。スレッドを開始し、完了したらメインスレッドに通知するように調整する方がよいでしょう。もちろん、スレッドが実行されている間はボタンを無効にする必要があります。

しかし、実際にはProcessMessagesを使用する必要がある場合は、このようなビジーなループでは行いません。長期間にわたる検索操作が完了するのを待つために、プロセッサ全体を使用することはあまり意味がありません。このように、よりインテリジェントなブロッキング・ループを使用:

  1. メッセージがキュー上に配置され、又は
  2. スレッドがシグナリングされる:いずれかまで

    while MsgWaitForMultipleObjects(1, Thread.Handle, False, 
        INFINITE, QS_ALLEVENTS)=WAIT_OBJECT_0+1 do 
        Application.ProcessMessages; 
    

    MsgWaitForMultipleObjects機能がブロックされます。スレッドは完了したときに通知されます。

ループは、スレッドが通知されると終了しますが、キューに入れられたメッセージも処理します。

+0

ループは 'WAIT_OBJECT_0'もチェックする必要があります。スレッドが終了すると、 'WAIT_OBJECT_0'が返されます。呼び出しスレッドのキューに保留中のメッセージがあると、 'WAIT_OBJECT_0 + 1'が返されます。 'WAIT_OBJECT_0'が返されるまでループを実行させておく必要がありますが、各繰り返しで' WAIT_OBJECT_0 + 1'をチェックする必要があります。 –

+0

@remyコードをもう一度読んでください。ループは、ハンドルが通知されるまで実行されます。 –

+0

申し訳ありませんが、 'INFINITE'タイムアウトに気付かなかった。 –