10

最近、ウィンドウのメッセージ ループを独自のスレッドに配置しようとしましたが、なぜメッセージを受信しないのか疑問に思いましたが、ウィンドウを作成したスレッドに Windows がメッセージを投稿することを知りました。あるスレッドでウィンドウを作成し、別のスレッドにそのウィンドウのメッセージを受信させるにはどうすればよいでしょうか? PostThreadMessage 関数を見てきましたが、ウィンドウを作成したスレッドがメッセージをリッスンする必要があると思います。これはまさに私が避けようとしているものなので、その関数は必要なものではありません。

これはよくある質問のようで、答えを得るためにグーグルでかなりの時間を費やしましたが、見つけることができません。

4

5 に答える 5

12

あるスレッドでウィンドウを作成し、別のスレッドにそのウィンドウのメッセージを受信させるにはどうすればよいでしょうか?

簡単な答えは...あなたはしません。メッセージを処理するスレッドにウィンドウを作成します。これが不可能な場合は、アプローチを再考する必要があります。

于 2010-12-03T16:11:25.653 に答える
7

Windows メッセージ ポンプは、実際には、Windows の WndProc 関数whileを使用してキューからメッセージを取り出して呼び出す単なるループです。PeekMessage()それにはもう少し続きがありますが、それが基本的な操作です。

そのため、whileループが実行されるスレッドは、ウィンドウが「実行」できる唯一のスレッドです。これが、私が今まで見たすべての Windows アプリケーションの構築方法です。

しかし、私は過去に、かなりの努力をすれば、複数のスレッドでウィンドウを使用して Windows アプリを構築できるはずだと考えていました。これについて考えてから長い時間が経過したため、お見せできるコードはありませんが、私が検討した 2 つのアプローチがありました。

  1. メイン スレッドに 1 つのメッセージ ポンプを保持します。ただし、メッセージ ポンプのコードを変更して、特定の実行中のスレッドに基づいwhileてワーカー スレッドにメッセージをディスパッチするようにします。これにはルックアップ マップが必要であり、計算コストが高くなる可能性があります。QueueUserAPCHWND

  2. ワーカー スレッドでまったく新しいメッセージ ポンプを作成します。すべてのwhileコードを作成する必要がありますが、これは非常に簡単です。Petzold の古典的な本 は、これを行うために必要なすべてのツールを提供します。

このアプローチは、考えられるアプリケーションのアーキテクチャの観点からは意味がないことに注意してください。アプリを合理的に構築すれば、ウィンドウを複数のスレッドで実行する必要はありません。ウィンドウ処理は 1 つのスレッドで行われ、操作は別の (または多数の) スレッドで行われます。しかし、これは興味深い研究分野であり、それが私をこの道に導いたのです。要するに、これを行う必要はなく、これを行うべきではないことは事実上確信していますが、これはあなたが行う方法かもしれません。

于 2010-12-03T16:21:48.867 に答える
5

不可能です。各ウィンドウはそれを作成したスレッドに属し、その所有権は譲渡できません。

メッセージ ポンプを別のスレッドに配置することは問題ではありません。各スレッドには、独自のメッセージ キューがあります。メッセージをウィンドウに送信または投稿すると、OS はそのウィンドウを所有しているスレッドを確認し、メッセージをそのスレッドのメッセージ キューに送ります。スレッドは、自分のメッセージ キュー以外は読み取ることができないため、別のスレッドのウィンドウのメッセージをスレッドに処理させることはできません。

John's answer の最初のアイデアのように、メッセージを別のスレッドに再ディスパッチできますが、汎用のメッセージ ハンドラーとして、それは価値があるよりも複雑になります。多くのメッセージはウィンドウの状態を変更することを意図していますが、ウィンドウ自体のスレッド以外で状態を変更することはできません。一部のメッセージは、意味のある戻り値を取得する目的で送信されますが、メッセージが処理されるまで何を返すかがわからないため、ワーカー スレッドがメッセージを処理するのを待ってブロックする必要があります。

実際にワーカー スレッドにオフロードできるメッセージの小さなセットを特定し、それらを特別に処理する方がよいでしょう。これを行うと、メッセージが別のスレッドで処理されるウィンドウは実際にはありません。通常のワーカー スレッドを作成するだけで、推論するのに混乱が少なくなります。

処理に多くの時間を必要とするメッセージがウィンドウに送信されているが、送信者が結果を知る必要がない場合、または処理を終了する前に結果を知っている場合は、 を呼び出して早期に応答ReplyMessageできます。 . これにより、ウィンドウのスレッドが追加の作業を行っている間、送信スレッドを実行し続けることができます。

于 2010-12-03T18:25:27.963 に答える
2

AttachThreadInputが機能するかどうかを確認できます。これにより、他のスレッドからのメッセージを処理できます。

ほとんどの場合、ウィンドウのメッセージは作成されたスレッドで処理されるため、これはそれほど一般的な質問ではありません。Goz の回答を参照してください。同意します。

メッセージ処理を別のスレッドに入れても何も得られないことに注意してください。GUI タスクを複数のスレッドに分割しないでください。処理/バックグラウンド タスクをスレッドに分割します。

于 2010-12-03T16:12:59.610 に答える
-1

これを参照してください:

msdn: http://msdn.microsoft.com/en-us/library/ms644946(v=vs.85).aspx

メッセージがポストされるスレッドは、メッセージ キューを作成している必要があります。そうでない場合、PostThreadMessage の呼び出しは失敗します。この状況を処理するには、次の方法を使用します。

1.イベントオブジェクトを作成し、スレッドを作成します。

2.WaitForSingleObject 関数を使用して、PostThreadMessage を呼び出す前に、イベントがシグナル状態に設定されるのを待ちます。

3.メッセージがポストされるスレッドで、ここに示すように PeekMessage を呼び出して、システムにメッセージ キューを作成させます。

PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)

4.イベントを設定して、投稿されたメッセージをスレッドが受信する準備ができていることを示します。

于 2013-04-26T13:26:10.437 に答える