You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 14:42:46