如何让C#控制台程序无while循环等待Ctrl+C退出并运行异步方法
解决C#控制台程序等待Ctrl+C退出时的高CPU占用问题
你可以通过非忙等待的方式替代空while循环,让线程进入阻塞状态(不占用CPU资源),同时正常运行异步方法。以下是两种常用方案:
方案一:使用ManualResetEventSlim(同步阻塞方式)
ManualResetEventSlim是轻量级的同步原语,能让线程等待直到收到信号,期间不会占用CPU。
using System.Threading; using System.Threading.Tasks; class Program { private static readonly ManualResetEventSlim _exitSignal = new ManualResetEventSlim(false); static void Main(string[] args) { Console.CancelKeyPress += OnCancelKeyPress; // 启动你的异步业务方法 _ = RunAsyncOperation(); Console.WriteLine("-> Press CTRL+C to Exit"); _exitSignal.Wait(); // 阻塞线程,直到收到退出信号 } static async Task RunAsyncOperation() { // 示例异步逻辑:每隔1秒输出一次 while (!_exitSignal.IsSet) { Console.WriteLine("异步任务正在运行..."); await Task.Delay(1000); } } static void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) { e.Cancel = true; // 阻止系统直接终止程序 _exitSignal.Set(); // 发送退出信号 Console.WriteLine("CancelKeyPress fired, exit..."); } }
方案二:使用异步Main + TaskCompletionSource(异步编程风格)
如果你的项目使用C# 7.1及以上版本,推荐用异步Main结合TaskCompletionSource,更贴合现代异步编程模式:
using System.Threading.Tasks; class Program { private static readonly TaskCompletionSource<bool> _exitTaskSource = new TaskCompletionSource<bool>(); static async Task Main(string[] args) { Console.CancelKeyPress += OnCancelKeyPress; // 同时运行异步业务和等待退出的任务 await Task.WhenAll(RunAsyncOperation(), _exitTaskSource.Task); } static async Task RunAsyncOperation() { // 示例异步逻辑 while (!_exitTaskSource.Task.IsCompleted) { Console.WriteLine("异步任务正在运行..."); await Task.Delay(1000); } } static void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) { e.Cancel = true; _exitTaskSource.TrySetResult(true); // 触发退出任务完成 Console.WriteLine("CancelKeyPress fired, exit..."); } }
为什么原来的while循环会高CPU?
空的while (isRunning) { }是忙等待——线程会持续循环检查条件,让对应的CPU核心一直处于100%占用状态。而上面的方案都是让线程进入等待队列,直到收到信号才唤醒,完全不消耗CPU资源。
内容的提问来源于stack exchange,提问作者uingtea
相关产品推荐
相关产品推荐

