欢迎来到代码驿站!

C代码

当前位置:首页 > 软件编程 > C代码

vc控制台程序关闭事件时的处理方式及注意点详解

时间:2022-04-18 11:43:41|栏目:C代码|点击:

百度可以找到很多关于这个问题解决的方法

关键控制台API函数:SetConsoleCtrlHandler

在支持C++ 11以上的编译器中,你可以这么做。

SetConsoleCtrlHandler([](DWORD fdwctrltype)->BOOL {
    if (fdwctrltype == CTRL_CLOSE_EVENT) {
        // 你的善后代码...
        return TRUE;
    }
    return FALSE;
}, TRUE);

最初这么做是很舒服的,但之后发现了问题:

Windows控制台在标记状态下,printf之类的输出函数,会阻塞在标记选择时(点控制台左上角-编辑-标记)。

这就导致了,我们的善后代码中,可能会死锁,例如你要优雅的结束一个线程,这个线程在最后的时候printf了。

线程里printf等待标记状态,SetConsoleCtrlHandler回调函数里等待线程结束,总之就是死锁。

我本来想着,去找到能够获取这种标记状态的控制台API,但找了很久都没有结果。

最后,我就考虑,有没有方法让printf不与标记状态发生死锁,答案是: 输出流重定向。

所以,代码变成这样:

SetConsoleCtrlHandler([](DWORD fdwctrltype)->BOOL {
    if (fdwctrltype == CTRL_CLOSE_EVENT) {
        char szbuf[0x1000];
        setvbuf(stdout, szbuf, _IOFBF, 0x1000);
        // 你的善后代码...
        return TRUE;
    }
    return FALSE;
}, TRUE);

这么做之后,世界果然更美好了,如果最后这些日志信息对你来说是重要的,那么你可能需要写更多代码去实现。

知识点扩展:

实例:

BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
DWORD e = 0;
switch (CEvent)
{
case CTRL_C_EVENT:
e = CTRL_C_EVENT;
break;
case CTRL_BREAK_EVENT:
e = CTRL_BREAK_EVENT;
break;
case CTRL_CLOSE_EVENT:
e = CTRL_CLOSE_EVENT;
break;
case CTRL_LOGOFF_EVENT:
break;
case CTRL_SHUTDOWN_EVENT:
break;
}
return true;
}
int main(int argc, char* argv[])
{
if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE) == FALSE)
{
//安装失败
return -1;
}
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); //手工产生一事件
}

上一篇:使用emacs编写C语言教程

栏    目:C代码

下一篇:将正小数转化为2-9进制小数的实现方法

本文标题:vc控制台程序关闭事件时的处理方式及注意点详解

本文地址:http://www.codeinn.net/misctech/199524.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有