.NET 6控制台应用取消Token源无效,Main函数阻塞问题排查
.NET 6控制台捕获Ctrl+C后无法正常退出的原因
问题描述
在.NET 6环境的简单控制台应用中,编写C#代码捕获Interrupt信号(即Ctrl+C),尝试通过触发CancellationTokenSource取消令牌让Main方法正常退出,但实际程序未退出且看不到“Exiting...”提示;修改Main方法逻辑后问题依旧。
原始Main方法代码
namespace ConsoleApp1 { public class Program { private static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); public static void Main(string[] args) { Console.CancelKeyPress += new ConsoleCancelEventHandler(InterruptHandler); Task.Delay(Timeout.Infinite, cancellationTokenSource.Token).Wait(); Console.WriteLine("Exiting..."); } private static void InterruptHandler(object? sender, ConsoleCancelEventArgs e) { cancellationTokenSource.Cancel(); } } }
修改后的Main方法代码
public static void Main(string[] args) { Console.CancelKeyPress += new ConsoleCancelEventHandler(InterruptHandler); while (cancellationTokenSource.IsCancellationRequested == false) Thread.Sleep(1000); Console.WriteLine("Exiting..."); }
原因分析
核心原因是默认情况下,按下Ctrl+C时,系统会在ConsoleCancelEventHandler执行完成后立即终止进程,导致后续的取消令牌逻辑、退出提示输出还没来得及执行,程序就被强制结束了。
两种写法失效的具体原因:
- 原始写法中,
InterruptHandler刚调用cancellationTokenSource.Cancel(),系统就直接终止进程,Task.Delay(...)的等待还未响应取消,Console.WriteLine("Exiting...")完全没机会执行。 - 修改后的写法同理,
IsCancellationRequested刚被设为true,进程就被系统强制终止,循环还没退出,退出提示无法输出。
解决方案
在InterruptHandler中设置ConsoleCancelEventArgs.Cancel = true,告诉系统不要自动终止进程,由我们自行控制退出逻辑:
private static void InterruptHandler(object? sender, ConsoleCancelEventArgs e) { e.Cancel = true; // 阻止系统强制终止进程 cancellationTokenSource.Cancel(); }
修改后,无论是用Task.Delay等待取消的写法,还是循环判断的写法,都能正常执行到Console.WriteLine("Exiting..."),最终Main方法会正常退出。
内容的提问来源于stack exchange,提问作者Shishir Gupta
相关产品推荐
相关产品推荐

