9 windows windows-xp windows-vista
我有一个与此处描述的问题非常类似的问题:http: //www.eggheadcafe.com/software/aspnet/30579866/prevent-vista-from-markin.aspx
该线程表明任务管理器将WM_NULL发送到进程,并期望进程在超时限制(5秒?)内使用此消息.当我谷歌搜索"WM_NULL挂"时,有许多引用相同的技术.
但是我在应用程序的队列中看不到任何WM_NULL消息,而它在一个冗长的操作上工作 - 我有一个辅助线程,每0.5秒切换到主线程并调用PeekMessage()查找WM_NULL,它没有'找到任何!
那么,Windows(Vista)用于确定应用程序是否挂起的方法是什么?
应用程序应该使用哪些消息,以便Windows认为应用程序是响应式的?
更多细节 :
除了PeekMessage()寻找WM_NULL之外,我们还为鼠标事件调用PeekMessage(),因为我们还想了解用户是否选择了窗口的某个区域,其中绘制了停止符号.如果选择了该区域,我们设置一个标志,主线程中的冗长操作会定期检查,如果选择了停止标志,则会停止.Vista的问题在于,当它声明应用程序没有响应时,它会用鬼窗替换它的窗口 - 请参阅PeekMessage()的说明:
如果顶级窗口停止响应消息超过几秒钟,系统会认为窗口没有响应,并将其替换为具有相同z顺序,位置,大小和可视属性的重影窗口.这允许用户移动它,调整其大小,甚至关闭应用程序.但是,这些是唯一可用的操作,因为应用程序实际上没有响应.在调试应用程序时,系统不会生成重影窗口.
这个鬼窗口不允许鼠标选择进入我们的窗口,因为窗口不再在屏幕上!所以我的目标是防止这个鬼窗首先出现......
在进行一些调查之后:
在我添加迈克尔在回答这个问题时建议的代码之后
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Run Code Online (Sandbox Code Playgroud)
该应用程序不再被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);
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,应用程序再次挂起!!
现在我真的被卡住了.如果我拦截了进来的唯一消息,让应用程序处理它们,那么为什么Windows仍然认为应用程序不处理事件?
任何有意义的建议都会非常感激.
TaskManager 可能使用IsHungAppWindow来确定应用程序是否挂起。根据 MSDN,如果应用程序不等待输入、不在启动处理中或在 5 秒内未处理消息,则该应用程序被视为挂起。所以不需要WM_NULL。
您不需要使用任何特定的消息 - 只需定期泵送消息并将长任务移出 UI 线程即可。如果您可以每 0.5 秒调用一次 PeekMessage,请将其替换为以下内容:
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Run Code Online (Sandbox Code Playgroud)
这将完全耗尽您的消息队列,并使您看起来对用户反应更快。不要过滤单个消息,例如鼠标消息。如果可能,您应该每 0.5 秒执行一次以上操作,并且从长远来看,尝试将长时间的工作移出 UI 线程。