【发布时间】:2014-09-20 17:21:06
【问题描述】:
基本信息:
语言是 c++ (visual c++ 2013)。 我的程序是一个 win32 应用程序,多线程(3 个线程),并且对于它的设计,它作为关键进程运行(使用 RtlSetProcessIsCritical,它完成了这项工作)。我可以以编程方式打开和关闭它(两个功能,一个将当前进程设置为关键,第二个将当前进程恢复为非关键)。
如果我只是单击开始-->关闭窗口,系统显然会因蓝屏死机而崩溃,如果你手动终止关键进程,你会得到同样的蓝屏。
如何检测 Windows 何时关闭/重新启动?所以我可以执行“转向非关键”功能,从而彻底关闭。 :)
其中一个线程由每 5 或 10 秒运行一次的循环组成,在此处添加 Windows 关闭检测听起来是唯一可行的选择。
我只尝试了一件事,WM_ENDSESSION 如此处所示http://msdn.microsoft.com/en-us/library/aa376889%28v=VS.85%29.aspx。但它“未能”检测到操作系统关闭,并以蓝屏死机告终。
我会发现一些非常有用的示例或信息。如果需要其他详细信息,请告诉我,我将在几个小时内访问存储我的程序的计算机。 谢谢。
编辑:为什么要投反对票?我正在学习并想问一些我无法解决的问题。
编辑:您能否提供一个示例,说明在哪里/如何在我的循环中添加对消息的实际检查?我无法克服这个问题,我已经在 switch 语句中得到了 WM_QUERYENDSESSION 的情况。谢谢。
---------------编辑:
我无法让它工作,无论我尝试什么都不会工作.. 我的伪代码程序:
thread 1
{
functionx();
functiony();
}
thread 2
{
functionz();
functionf();
}
thread 3
{
for (;;)
{
functiong();
functionh();
}
}
int main()
{
thread 1;
thread 2;
thread 3;
}
对于 GetMessage 部分,我使用了这里的代码 http://www.winprog.org/tutorial/window_click.html 并重新调整以满足我的需要:
HWND hwnd;
MSG Msg;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_QUERYENDSESSION:
function_to_turn_critical_process_OFF();
return 0;
break;
case WM_ENDSESSION:
function_to_turn_critical_process_OFF();
return 0;
break;
}
return 0;
}
消息循环:
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
好的,如果我在 main() 中插入消息循环作为执行的第一件事,我遇到了问题 1,GetMessage 似乎让整个事情进入睡眠状态,所以我的程序甚至没有开始做他的事情。
如果我在 main() 中插入消息循环作为执行的最后一件事(在线程 3 下),我会遇到问题 2,因为线程 3 永远不会结束(永远循环)消息循环可能永远不会开始。此外,线程 3 循环包含几秒钟的小睡眠,我试图将获取消息循环放在那里,但它未能捕获它,我无法删除原始代码,无法更改循环或删除小睡眠功能。
如果我在线程 3 循环中插入消息循环,它只是无法检测到 WM_QUERYENDSESSION,我最终在 Windows 关闭时出现 BSOD,因此我的“关闭关键关闭”功能没有被执行。
我能做什么?谷歌对这件事没有帮助。我知道在一个简单的程序中,我应该将消息循环放在 main 中,它会一直工作到最后,但我在这里发疯了,试图在我的代码中为这个消息循环找到一个位置。
任何帮助表示赞赏..
【问题讨论】:
-
您的消息循环中是否收到任何消息?下面的 WM_QUERY_ENDSESSION 消息答案是正确的。您的程序 main 应该创建一个窗口,启动您的工作线程,然后执行消息处理循环。当您处理 WM_ENDSESSION 时,更改应用程序优先级,并可能发出信号让线程优雅地结束(SetEvent 或类似的东西)。
标签: c++ windows multithreading winapi visual-c++