2

我们有一个不响应任何用户输入的 MFC Visual-C++ 应用程序。

(注意:目前仅在一台机器上知道。该行为偶尔会再次出现,但仅在应用程序运行几天后才会出现!)

当我们通过 Alt-Tab(或任务栏)切换到应用程序时,应用程序会被重绘,但我们不能,例如,通过单击标题栏来激活它的主窗口。


我们已经使用 WinDbg 提取了 4 个转储并检查了活动指令。我们总是在主线程(GUI线程)内的一些重绘代码或类似的东西中。我们肯定是/不在模式消息循环中,并且主线程的堆栈总是看起来“OK”。(大多数/所有工作线程都处于空闲状态,等待某个事件,那里也没有可疑代码。)


在调查Spy++的问题时,我们还看到这个单独的问题中指定的行为,即我们似乎收到了绘制和激活消息,但没有用户输入被路由到应用程序。当我在屏幕上有应用程序窗口并选择它以显示主窗口的消息时,

应用程序主窗口

它只会显示“通用”“referesh”消息而不会显示其他信息

主窗口的消息

如果我钻得更深,并选择整个过程的所有消息,

相同进程设置的窗口

这就是我们所看到的:

每秒 200 条 WM_PAINT 消息

该应用程序显然只在一个隐藏的子窗口 (00CB09F0) 上处理消息,我们看到的是每秒 200 条 WM_PAINT 消息的恒定流。

通常,此子窗口根本不处理任何消息(Windows 发送消息时刷新 WM_PAINT 等除外)。它通常用作绘图区域,并且通过其父 (010A09B8) 窗口上的 WM_TIMER 消息进行绘图。(这个 WM_TIMER 消息也不会显示在挂起的应用程序上。)

进程资源管理器中显示的性能配置文件如下所示(100% 内核时间,或多或少):

Process Explorer 应用程序性能图

4

2 回答 2

0

我会说你在那个接收 WM_PAINT 洪水的窗口中有一个重绘循环。

Invalidate如果您直接或间接地从 WM_PAINT 消息的处理中调用或类似方法,通常会发生这种情况。

其他可能性是,由于您说您正在使用计时器来重绘窗口,因此实际绘制所花费的时间比它自己的时间更多,因此消息堆积在队列中。

另一种可能性是,您正在从与制作绘画的线程不同的线程中使窗口无效。

无论如何,您应该确保您Invalidate*()正确调用(您没有显示任何代码),而不是从OnPaint事件中调用。并且避免调用UpdateWindow(),因为如果不小心调用这个函数会弄乱事情。

于 2011-11-18T22:48:14.930 回答
0

当从对话框中抛出异常时,我已经看到了这个问题。MFC 的 DoModal 函数禁用主程序窗口,然后在对话框返回时重新启用它;异常绕过重新启用部分,主窗口永远保持禁用状态。

于 2011-11-18T22:54:27.503 回答