我有一个非常类似于这里描述的问题: https://microsoft.public.win32.programmer.kernel.narkive.com/Ly2P8Yp2/prevent-vista-from-marking-my-application-as-non-responding
那个线程建议任务管理器向进程发送WM_NULL消息,并期望进程在超时限制(5秒?)内消耗此消息。 当我搜索“WM_NULL hung”时,有许多引用相同的技术。
然而,在我的应用程序在进行漫长的操作时,我没有看到任何WM_NULL消息在队列中 - 我有一个辅助线程,每0.5秒切换到主线程并调用PeekMessage()查找WM_NULL,但它没有发现任何消息!
那么,Windows(Vista)用于确定应用程序是否挂起的方法是什么?
我的应用程序应该消耗哪些消息,以便Windows认为应用程序是响应的?
更多细节:
除了使用PeekMessage()查找WM_NULL,我们还会调用PeekMessage()来处理鼠标事件,因为我们还想了解用户是否选择了窗口中绘制了停止标志的某个区域。如果选择了该区域,我们会设置一个标志,主线程中的冗长操作会定期检查该标志,并在选择了停止标志时停止。 Vista存在的问题是,当它将应用程序声明为无响应时,它会用幽灵窗口替换其窗口 - 请参见description of PeekMessage():“如果顶层窗口在几秒钟内停止响应消息,系统认为该窗口无响应,并用具有相同z顺序、位置、大小和视觉属性的幽灵窗口替换它。这使得用户可以移动它、调整它的大小或甚至关闭应用程序。但是,这些都是唯一可用的操作,因为应用程序实际上没有响应。当应用程序正在进行调试时,系统不会生成幽灵窗口。”
这个幽灵窗口不允许鼠标选择通过到达我们的窗口,因为窗口不再显示在屏幕上! 因此,我的目标是防止这个幽灵窗口首先出现...
经过进一步调查后:
在我添加了Michael在回答这个问题时建议的代码之后
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
应用程序现在不再被Windows视为挂起状态;但是我无法使用此解决方案,因为应用程序开始对各种按钮等做出反应(这不应该发生)。 因此,我尝试查看哪些消息正在到达。我使用了Spy++和调试打印,两者都只显示了两种类型的消息:WM_TIMER和0x0118(WM_SYSTIMER)。因此,我修改了代码如下:
while (PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE) ||
PeekMessage(&msg, NULL, 0x0118, 0x0118, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
令人惊讶的是,应用程序又卡住了!!
现在我真的陷入困境了。如果我截获所有进来的消息,并让应用程序处理它们,为什么Windows还认为应用程序没有处理事件?
非常感谢任何有意义的建议。