windows - Windows(特别是 Vista)如何确定我的应用程序是否挂起?

标签 windows windows-vista windows-xp

我遇到的问题与此处描述的问题非常相似: http://www.eggheadcafe.com/software/aspnet/30579866/prevent-vista-from-markin.aspx

该线程建议任务管理器向进程发送 WM_NULL 并期望进程在超时限制(5 秒?)内使用此消息。 当我在 google 上搜索“WM_NULL hung”时,有很多对相同技术的引用。

但是,当我的应用程序进行长时间操作时,我没有在我的应用程序队列中看到任何 WM_NULL 消息 - 我有一个辅助线程,每 0.5 秒切换到主线程并调用 PeekMessage() 寻找 WM_NULL,并且它没有找到任何东西!

那么,Windows(Vista)用什么方法判断一个应用程序是否挂起呢?

我的应用程序应该使用哪些消息,以便 Windows 认为该应用程序具有响应能力?

更多详情:

除了寻找 WM_NULL 的 PeekMessage() 之外,我们还为鼠标事件调用 PeekMessage(),因为我们还想了解用户是否选择了窗口的某个区域,其中绘制了一个停止标志。如果该区域被选中,我们设置一个标志,主线程中的冗长操作会定期检查,如果停止标志被选中,则会停止。 Vista 的问题在于,当它声明应用程序无响应时,它会将其窗口替换为幻影窗口 - 参见 description of PeekMessage() :

If a top-level window stops responding to messages for more than several seconds, the system considers the window to be not responding and replaces it with a ghost window that has the same z-order, location, size, and visual attributes. This allows the user to move it, resize it, or even close the application. However, these are the only actions available because the application is actually not responding. When an application is being debugged, the system does not generate a ghost window.

这个幽灵窗口不允许鼠标点击进入我们的窗口,因为窗口不再在屏幕上了! 所以我的目标是首先防止这个幽灵窗口出现......

经过更多调查:

添加代码后 Michael在他对这个问题的回答中建议

while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

该应用程序不再被 Windows 视为挂起;但是我不能使用这个解决方案,因为应用程序开始对各种按钮等的选择使用react(这不应该发生)。 所以我试着看看有哪些消息进来了。我使用了 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 仍然认为应用程序不处理事件?

任何有意义的建议将不胜感激。

最佳答案

TaskManager 可能使用 IsHungAppWindow以确定应用程序是否挂起。根据 MSDN,如果应用程序不等待输入、不在启动处理中或未在 5 秒内处理消息,则该应用程序被视为挂起。所以不需要 WM_NULL。

您无需使用任何特定消息 - 只需定期发送消息并将长任务移出 UI 线程即可。如果您可以每 0.5 秒调用一次 PeekMessage,请将其替换为:

while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

这将完全耗尽您的消息队列,并使您对用户的 react 更加灵敏。不要过滤单个消息,例如鼠标消息。如果可能,您应该每 0.5 秒执行一次以上操作,并且长期尝试将长时间的工作移出 UI 线程。

关于windows - Windows(特别是 Vista)如何确定我的应用程序是否挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/842161/

相关文章:

windows - FATAL : No bootable medium found! 系统停止

audio - 使用 FFMPEG 的音频流中的麦克风问题

windows - 如何在 Delphi 的多线程中加载一个 DLL?

c# - 如何通过C#在windows 2008 windows中安装IIS

c++ - 播放音频文件并调整系统音量

windows - 诊断 Windows 应用程序 list

windows - COM服务真的不能同时被多个程序使用吗?

windows - 通过快捷方式休眠会导致计划任务无法唤醒计算机

dll - 如何在vista中将dll添加到gac

c# - 使用脚本编辑 windows xp 注册表