如何让命令行运行的控制台程序实现优雅退出并执行清理代码?
控制台应用优雅退出实现方案
可以实现非IDE调试场景下的优雅退出,核心是同时处理ESC按键捕获和Ctrl+C终止信号,确保清理代码在两种退出触发方式下都能执行。
实现步骤
注册Ctrl+C信号处理事件
通过Console.CancelKeyPress事件捕获用户按下的Ctrl+C,阻止系统直接终止进程,转而执行自定义清理逻辑。后台线程监听ESC按键
启动一个后台线程,循环检查按键输入,捕获ESC键后触发退出流程。统一退出标记与清理逻辑
用共享变量标记退出状态,让业务逻辑能及时终止,同时编写独立的清理方法,确保两种退出路径都能调用。
完整代码示例
using System; using System.Threading; class Program { private static bool _isExiting = false; static void Main(string[] args) { // 处理Ctrl+C终止信号 Console.CancelKeyPress += (sender, e) => { e.Cancel = true; // 阻止系统强制杀死进程 TriggerExit("收到Ctrl+C终止信号"); }; // 启动ESC按键监听线程 var keyListener = new Thread(() => { while (!_isExiting) { if (Console.KeyAvailable) { var key = Console.ReadKey(true); // true表示不回显按键 if (key.Key == ConsoleKey.Escape) { TriggerExit("按下ESC键"); } } Thread.Sleep(100); // 降低线程CPU占用 } }); keyListener.IsBackground = true; keyListener.Start(); // 模拟业务逻辑循环 Console.WriteLine("程序运行中,按ESC或Ctrl+C退出..."); while (!_isExiting) { Console.WriteLine("执行业务任务..."); Thread.Sleep(1000); } } private static void TriggerExit(string triggerMessage) { if (_isExiting) return; // 避免重复触发 _isExiting = true; Console.WriteLine($"\n{triggerMessage},开始执行清理..."); Cleanup(); Console.WriteLine("程序已优雅退出。"); Environment.Exit(0); } private static void Cleanup() { // 替换为你的实际清理逻辑:释放资源、保存数据、关闭连接等 Console.WriteLine("清理操作完成。"); } }
效果说明
- IDE调试场景:
Console.WriteLine输出会显示在IDE的Output窗口,ESC按键和Ctrl+C都能触发优雅退出,执行清理代码。 - 命令行运行场景:输出显示在命令窗口,ESC按键可直接捕获,Ctrl+C也会触发自定义清理流程,不会直接杀死进程。
内容的提问来源于stack exchange,提问作者Arvo Bowen
相关产品推荐
相关产品推荐

