2

ユーザー入力に反応しない MFC Visual-C++ アプリケーションがあります。

(注: 現在、1 台のマシンでのみ確認されています。この動作はときどき再発しますが、アプリを数日間実行した後でのみ発生します!)

アプリケーション、Alt-Tab (またはタスク バー) で切り替えると再描画されますが、たとえば、タイトル バーをクリックしてメイン ウィンドウをアクティブにすることはできません。


WinDbg を使用して既に 4 つのダンプをプルし、アクティブな命令を確認しました。私たちは常に、メイン スレッド (GUI スレッド) 内でコードの再描画などを行っていました。私たちは間違いなくモーダル メッセージ ループに陥っていた/していないので、メイン スレッドのスタックは常に「OK」に見えました。(ほとんど/すべてのワーカー スレッドはアイドル状態で、何らかのイベントを待っていましたが、疑わしいコードもありませんでした。)


Spy++で問題を調査すると、この別の質問でも指定されている動作が見られます。つまり、ペイントとアクティベーション メッセージを取得しているように見えますが、ユーザー入力はアプリケーションにルーティングされません。画面にアプリケーションウィンドウがあり、それを選択してメインウィンドウのメッセージを表示すると、

アプリのメイン ウィンドウ

「一般的な」「参照」メッセージのみが表示され、他には何も表示されません

メイン ウィンドウのメッセージ

さらに掘り下げて、プロセス全体のすべてのメッセージを選択すると、

同じプロセス設定のウィンドウ

これが私たちが見るものです:

1 秒あたり 200 の WM_PAINT メッセージ

アプリは明らかに 1 つの非表示のサブウィンドウ (00CB09F0) でのみメッセージを処理しており、そこには1 秒あたり 200 の WM_PAINT メッセージの一定のストリームが表示されます。

通常、このサブ ウィンドウはメッセージをまったく処理していません (Windows がメッセージを送信するときの WM_PAINT などの更新を除く)。これは通常、描画領域として使用され、描画はその親 (010A09B8) ウィンドウの WM_TIMER メッセージによって行われます。(ただし、この WM_TIMER メッセージはハングしているアプリにも表示されません。)

プロセス エクスプローラーに表示されるパフォーマンス プロファイルは次のようになります (100% カーネル時間、多かれ少なかれ):

Process Explorer アプリのパフォーマンス グラフ

4

2 に答える 2

0

ダイアログから例外がスローされたときにこの問題が発生しました。MFCのDoModal関数は、メインプログラムウィンドウを無効にし、ダイアログが戻ったときに再び有効にします。例外は再有効化部分をバイパスし、メインウィンドウは永久に無効のままになります。

于 2011-11-18T22:54:27.503 に答える
0

そのウィンドウに WM_PAINT フラッドを受け取る再描画ループがあると思います。

Invalidateこれは通常、WM_PAINT メッセージの処理から直接的または間接的に呼び出すなどの場合に発生します。

他の可能性は、タイマーを使用してウィンドウを再描画していると言っているため、実際の描画にはそれ自体の時間よりも多くの時間がかかっているため、メッセージがキューに山積みになっている可能性があります。

さらに別の可能性として、描画を作成しているスレッドとは別のスレッドからウィンドウを無効にしている可能性があります。

とにかく、イベントからではなく、適切に呼び出しInvalidate*()ていること (コードを表示していないこと)を確認する必要がありOnPaintます。またUpdateWindow()、この関数は少し注意せずに呼び出すと混乱する可能性があるため、呼び出しは避けてください。

于 2011-11-18T22:48:14.930 に答える