12

OTLを使用してスレッド内にメッセージ・ループを実装するにはどうすればよいですか? Application.ProcessMessages; これまで使用していたものですが、使用するのはあまり安全ではありません。

ありがとう

4

2 に答える 2

17

これは、スレッドのキューからメッセージを取り出す方法です。

while GetMessage(Msg, 0, 0, 0) and not Terminated do begin
  Try
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  Except
    Application.HandleException(Self);
  End;
end;

を使用Application.ProcessMessagesすると、呼び出しスレッドのキューのメッセージがプルされます。ただし、ブロックしないため、メッセージ ループで使用するのは適切ではありません。を使用するのはそのためですGetMessage。キューが空の場合はブロックされます。また、スレッドセーフになるように設計されていないApplication.ProcessMessages他のメソッドも呼び出します。TApplicationしたがって、メインスレッド以外のスレッドから呼び出さない理由はたくさんあります。

スレッドを終了する必要がある場合は、次のようにします。

Terminate;
PostThreadMessage(ThreadID, WM_NULL, 0, 0);
//wake the thread so that it can notice that it has terminated

これはいずれも OTL 固有のものではありません。このコードはすべて、TThread子孫に存在することを意図しています。ただし、アイデアは譲渡可能です。


コメントでは、ビジーでノンブロッキングのメッセージ ループを実行することを示します。あなたはPeekMessageそのために使うでしょう。

while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do begin
  Try
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  Except
    Application.HandleException(Self);
  End;
end;
于 2012-12-18T11:22:37.710 に答える
3

Application.Run と同様のループを作成できます。

PeekMessageメッセージが利用可能かどうかを確認するを呼び出すことができます。PeekMessage は現在のスレッドのメッセージ キューをチェックするため、スレッドで使用する場合は、スレッドのメッセージ キュー (PostThreadMessage を使用してメッセージを投稿できる) をチェックします。

PeekMessage の代わりにGetMessage、メッセージが受信されるまで待機する を使用することもできます。GetMessage 0を返しますfalse*)

これWM_QUITは、メッセージ ループを終了するシグナルでもあります。その後、GetMessage を再度呼び出すのは危険です。別のメッセージが受信されない可能性があり、アプリケーションがブロックされているために適切に終了できなくなる可能性があるためです。

Application.ProcessMessages は、メイン スレッドに固有の多くの余分な処理を行うため、実際にはあまり安全ではありません。1 つは、メッセージ キューが空になるとすぐに Application.OnIdle をトリガーすることです。これは、(問題 1) スレッド メッセージ キューが空で、(問題 2) スレッドのコンテキストでそれを呼び出すことを意味します。イベントでの VCL インタラクション。

* ) GetMessage の戻り値について: Delphi が GetMessage を LongBool を返すように実装していることに気付きました。ただし、実際の戻り値は整数です。WM_QUIT の場合は 0、エラーの場合は -1、それ以外の場合は 0 以外を返します。マイクロソフトは次のように述べています

戻り値はゼロ以外、ゼロ、または -1 になる可能性があるため、次のようなコードは避けてください。

while (GetMessage( lpMsg, hWnd, 0, 0)) ...

残念ながら、GetMessage を正しく使用するには、別のエイリアスで GetMessage をインポートする必要があります。

于 2012-12-18T11:20:52.953 に答える