スレッド A にウィンドウがあり、ある時点で (wndproc でメッセージを受信した結果として) スレッド B でアクションをトリガーし、アクションが完了するのを待ちます (ある種の同期メカニズムを使用)。次に、スレッド B が を呼び出しMoveWindow()
て、子ウィンドウをスレッド A のウィンドウ (標準のテキスト ボックスなど) 内に移動します。この時点で、プログラムは何らかの理由でデッドロック状態になります。MoveWindow()
がスレッド A から呼び出されている場合、すべてが機能します。理由はありますか?
5 に答える
MoveWindowの代わりに、フラグSWP_ASYNCWINDOWPOSでSetWindowPosを使用できます。
その理由は、ThreadAがThreadBが何らかのイベントを処理するのを待機しているのに対し、ThreadBはThreadA(ウィンドウを所有しているスレッド)がMoveWindowの結果を返すのを待機しているためである可能性があります。
@1800 さんの説明が一番近いと思います。
ウィンドウを所有していないスレッドからウィンドウを移動する場合、移動したウィンドウのウィンドウ プロシージャに WM_WINDOWPOSCHANGING などを渡すために Windows は SendMessage を使用しないと思います。代わりに、ウィンドウ プロシージャが正しいスレッドでのみ呼び出されるようにするために、WM_WINDOWPOSCHANGING メッセージをポストし、正しいスレッドで実行されているイベント ループによって選択されるまでブロックします。ただし、そのイベント ループは実行されていません。ブロックされており、MoveWindow が完了するのを待っています。
@totaland と @Logan Capaldo のソリューションが機能します。
ウィンドウが移動するまで待つ必要はないかもしれません。または、確実に行う必要がある場合は、MsgWaitForMultipleObjectsEx を使用して小さなイベント ループを実行し、投稿されたメッセージを処理します。
「ある種の同期メカニズム」とは何ですか? WaitFor(Multiple)Object(s) の場合は、 [MsgWaitForMultipleObjects]( http://msdn.microsoft.com/en-us/library/ms684242(VS.85).aspx) ( Ex代わりにウェイクアップするあなたがメッセージを持っていて、ルセロが提案するようにそれを発送するとき。
待機中にスレッドのメッセージ ポンプが実行されていることを確認する必要があります。
PeekMessage() (またはおそらくGetMessage() ) およびDispatchMessage()でループしたい場合があります。
ユーザー インターフェイス オブジェクトのスレッド アフィニティ、パート 1: ウィンドウ ハンドル:
異なるオブジェクトには異なるスレッド アフィニティ ルールがありますが、基本的な原則は 16 ビット Windows に由来します。
最も重要なユーザー インターフェイス要素は、もちろんウィンドウです。ウィンドウ オブジェクトにはスレッド アフィニティがあります。ウィンドウを作成するスレッドは、ウィンドウが切り離せない関係にあるスレッドです。非公式に、スレッドがウィンドウを「所有している」と言います。メッセージは、それを所有するスレッドでのみウィンドウ プロシージャにディスパッチされます。一般的に言えば、ウィンドウへの変更は、それを所有するスレッドからのみ行う必要があります。ウィンドウ マネージャは、ウィンドウ プロパティ、スタイル、およびウィンドウ プロシージャなどのその他の属性などへのアクセスを任意のスレッドに許可し、そのようなアクセスはウィンドウ マネージャの観点からはスレッド セーフですが、通常、ロード、変更、書き込みのシーケンスは制限する必要があります。所有者スレッドに。