控制台退出事件仅持续5秒,如何确保清理函数执行完成?
解决方案:突破控制台关闭时5秒的清理时间限制
Windows系统对控制台进程的SetConsoleCtrlHandler回调函数默认设置了5秒超时,超时后会强制终止进程。要确保清理操作有足够时间完成,可通过以下方式解决:
核心思路
当收到控制台关闭信号时,让回调函数返回true,告知系统我们将自行处理退出逻辑,这样系统就不会触发5秒后的强制终止。随后通过退出标志让主循环结束,在主流程中执行完整的清理操作。
修改后的代码
using System; using System.Runtime.InteropServices; using System.Threading; namespace ConsoleApp1 { public class Test { [DllImport("Kernel32")] private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add); private delegate bool SetConsoleCtrlEventHandler(CtrlType sig); private enum CtrlType { CTRL_C_EVENT = 0, CTRL_BREAK_EVENT = 1, CTRL_CLOSE_EVENT = 2, CTRL_LOGOFF_EVENT = 5, CTRL_SHUTDOWN_EVENT = 6 } // 退出标志,用于通知主循环终止 private static bool _isExiting = false; private static bool Handler(CtrlType signal) { switch (signal) { case CtrlType.CTRL_BREAK_EVENT: case CtrlType.CTRL_C_EVENT: case CtrlType.CTRL_LOGOFF_EVENT: case CtrlType.CTRL_SHUTDOWN_EVENT: case CtrlType.CTRL_CLOSE_EVENT: Console.WriteLine("开始执行清理操作..."); _isExiting = true; // 返回true,告诉系统我们自行处理退出,避免5秒强制终止 return true; default: return false; } } public static void Main(string[] args) { // 注册控制台信号处理器 SetConsoleCtrlHandler(Handler, true); // 主业务循环 while (!_isExiting) { Thread.Sleep(50); // 这里可以添加你的业务逻辑 } // 执行清理操作,这里有足够时间完成所有任务 Console.WriteLine("正在清理资源..."); // 示例:模拟耗时的清理操作 Thread.Sleep(10000); // 10秒的清理任务 Console.WriteLine("清理完成,进程即将退出"); Environment.Exit(0); } } }
关键说明
- 返回true的作用:回调函数返回
true会阻止系统执行默认的终止流程,取消5秒倒计时强制关闭的逻辑。 - 退出标志的使用:通过
_isExiting标志让主循环优雅退出,将清理操作放在主流程中执行,避免在信号回调线程中执行过长任务(信号回调线程属于系统线程,长时间占用可能引发其他问题)。 - 特殊场景处理:如果是处理系统注销/关机信号(
CTRL_LOGOFF_EVENT、CTRL_SHUTDOWN_EVENT),系统最终仍会强制终止进程,但此时的超时时间会比5秒更长,足以完成大部分常规清理任务。
内容的提问来源于stack exchange,提问作者matteoreda996
相关产品推荐
相关产品推荐

