OTLを使用してスレッド内にメッセージ・ループを実装するにはどうすればよいですか? Application.ProcessMessages; これまで使用していたものですが、使用するのはあまり安全ではありません。
ありがとう
OTLを使用してスレッド内にメッセージ・ループを実装するにはどうすればよいですか? Application.ProcessMessages; これまで使用していたものですが、使用するのはあまり安全ではありません。
ありがとう
これは、スレッドのキューからメッセージを取り出す方法です。
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;
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 をインポートする必要があります。