我希望能够在c#控制台应用程序中捕获Ctrl+C,以便在退出之前执行一些清理。做这件事最好的方法是什么?
当前回答
控制台。TreatControlCAsInput = true;对我很有效。
其他回答
控制台。TreatControlCAsInput = true;对我很有效。
看到MSDN:
控制台。CancelKeyPress事件
带有代码示例的文章:
Ctrl-C和.NET控制台应用程序
我可以在离开前做一些清理工作。做这件事最好的方法是什么 这才是真正的目标:走出陷阱,做你自己的东西。以上两个答案都不是正确的。因为Ctrl+C只是退出应用程序的众多方法之一。
在dotnet c#中需要什么-所谓的取消令牌传递给Host.RunAsync(ct),然后,在退出信号陷阱中,对于Windows它将是
private static readonly CancellationTokenSource cts = new CancellationTokenSource();
public static int Main(string[] args)
{
// For gracefull shutdown, trap unload event
AppDomain.CurrentDomain.ProcessExit += (sender, e) =>
{
cts.Cancel();
exitEvent.Wait();
};
Console.CancelKeyPress += (sender, e) =>
{
cts.Cancel();
exitEvent.Wait();
};
host.RunAsync(cts);
Console.WriteLine("Shutting down");
exitEvent.Set();
return 0;
}
...
控制台。CancelKeyPress事件用于此。下面是它的用法:
public static void Main(string[] args)
{
Console.CancelKeyPress += delegate {
// call methods to clean up
};
while (true) {}
}
当用户按Ctrl+C时,委托中的代码将运行,程序将退出。这允许您通过调用必要的方法来执行清理。请注意,执行委托之后没有代码。
在其他情况下,这是行不通的。例如,如果程序当前正在执行不能立即停止的重要计算。在这种情况下,正确的策略可能是告诉程序在计算完成后退出。下面的代码给出了如何实现的示例:
class MainClass
{
private static bool keepRunning = true;
public static void Main(string[] args)
{
Console.CancelKeyPress += delegate(object? sender, ConsoleCancelEventArgs e) {
e.Cancel = true;
MainClass.keepRunning = false;
};
while (MainClass.keepRunning) {
// Do your work in here, in small chunks.
// If you literally just want to wait until Ctrl+C,
// not doing anything, see the answer using set-reset events.
}
Console.WriteLine("exited gracefully");
}
}
这段代码与第一个示例之间的区别在于,e.Cancel被设置为true,这意味着在委托之后继续执行。如果运行,程序等待用户按Ctrl+C。当这种情况发生时,keepprunning变量会改变值,从而导致while循环退出。这是一种使程序优雅退出的方法。
我想补充一下乔纳斯的回答。在bool上旋转将导致100%的CPU利用率,并且在等待CTRL+C时浪费大量的能量。
更好的解决方案是使用ManualResetEvent来实际“等待”CTRL+C:
static void Main(string[] args) {
var exitEvent = new ManualResetEvent(false);
Console.CancelKeyPress += (sender, eventArgs) => {
eventArgs.Cancel = true;
exitEvent.Set();
};
var server = new MyServer(); // example
server.Run();
exitEvent.WaitOne();
server.Stop();
}
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 为什么Visual Studio 2015/2017/2019测试运行器没有发现我的xUnit v2测试
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 没有ListBox。SelectionMode="None",是否有其他方法禁用列表框中的选择?
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- console.log()和console.debug()的区别?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?