1

追加のスレッドから WIN32 API を使用しようとすると、デッドロックが発生します。フレーム レートを改善するには、アプリケーションで追加のスレッドが必要です。実際には役に立ちますが、ほとんどすべてのシステム機能でデッドロックが発生します。

::ShowWindow ::MoveWindow ::UpdateWindow

たとえば、ShowWindow() を ShowWindowAsync() に置き換えることができ、それで問題が解決することはわかっていますが、MoveWindow() と UpdateWindow() にはそのような代替手段はありません。

誰かがそれらの問題を経験しましたか?解決策は何ですか?

ありがとう!

4

2 に答える 2

1

「デッドロック」という用語は、2 つのスレッドが別のスレッドによってロックされているリソースへのアクセスを待機している、非常に特殊なことを表しています。これがあなたのケースで起こっていることを示すものはありません (または存在しますか?)。また、マルチスレッドで達成したいことは正確には何ですか?

いずれにせよ、UI を 1 つのスレッドに保持し、SendMessage() & Co を使用して、バックグラウンド スレッドで発生するイベントをそのスレッドに通知します。または、タイマーを使用して特定の状態変化をポーリングすることもできます。そうすれば、安全側にいて、アプリケーションがロックすることはありません (少なくとも異なるスレッドから UI を使用することが原因ではありません)。

もう少し正確に言うと、ウィンドウとそのすべての子ウィンドウのメッセージ ループを 1 つのスレッドに保持する必要があります。複数のウィンドウを作成し、それぞれのスレッドからそれぞれを処理できますが、呼び出しを混在させないでください。実際には、複数のウィンドウを作成するアプリケーションはほとんどないため、この区別は重要ではありません (メッセージ ボックスやその他のダイアログなどはカウントされません)。

于 2013-06-02T21:52:44.767 に答える
1

参照するすべての API 関数には、ターゲット ウィンドウに何らかのメッセージを送信 (!) するという共通点があります。UpdateWindow は、WM_PAINT を送信する必要があるため、おそらく最も明白です。メッセージを「送信」し、キューに投稿しないことにも注意してください (UpdateWindow の場合、MSDN のドキュメントではこれを明示的に呼び出していますが、それ以外の場合はあまり明白ではない可能性があります)。

また、一部のコメントで言及されているように、ウィンドウにはスレッド アフィニティがあることに注意してください。とりわけ、これは、そのウィンドウへのメッセージが 1 つのスレッドでのみ受信/ディスパッチされることを意味します。別のスレッドのウィンドウにメッセージを送信した場合、オペレーティング システムは、そのメッセージをいつディスパッチするか (つまり、ウィンドウ プロシージャを呼び出すか) を決定するタスクを残されます。これ (着信送信メッセージのディスパッチ) は、ランダム メッセージでウィンドウ プロシージャを安全に呼び出すことができる特定の API 呼び出し中にのみ発生します。関連する時間は、GetMessage と PeekMessage* の間です。

そのため、ウィンドウ所有スレッド (UI スレッドとも呼ばれます) がメッセージを正常にポンピングしている場合、着信送信メッセージも迅速にディスパッチされます。ただし、あなたの質問からは、UI スレッドが現在ビジーであるようです。次に、2 番目のスレッドが上記の関数の 1 つを呼び出すと、最初のスレッドが送信されたメッセージをディスパッチする機会を提供するまでブロックされます。

他の人が言ったように、通常はユーザー インターフェイス コードを 1 つの専用 UI スレッドに保持することをお勧めします (例外はありますが、常にそうであるように、ルールは証明されています)。また、ウィンドウを所有するスレッドが常にメッセージに応答できるようにすることは、(優れたユーザー エクスペリエンスのために) 絶対に必要です。UI スレッドも一部の同期オブジェクトを待機する必要がある場合は、MsgWaitForMultipleObjects が役立つことがあります。

*リストは完全ではない可能性があります。

于 2013-06-02T23:33:29.347 に答える