我如何继续运行我的控制台应用程序,直到一个键按下(如Esc按下?)
我假设它环绕着一个while循环。我不喜欢ReadKey,因为它阻塞操作并要求一个键,而不是只是继续听按键。
如何做到这一点呢?
我如何继续运行我的控制台应用程序,直到一个键按下(如Esc按下?)
我假设它环绕着一个while循环。我不喜欢ReadKey,因为它阻塞操作并要求一个键,而不是只是继续听按键。
如何做到这一点呢?
当前回答
最短的方法:
Console.WriteLine("Press ESC to stop");
while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
{
// do something
}
Console. readkey()是一个阻塞函数,它会停止程序的执行并等待按键,但多亏了检查Console。KeyAvailable键,while循环不会被阻塞,而是一直运行,直到按下Esc键。
其他回答
如果你正在使用Visual Studio,那么你可以在调试菜单中使用“开始不调试”。
它会自动写“按任意键继续…”到控制台完成应用程序后,它会让控制台为您打开,直到按下一个键。
处理一些其他答案不能很好处理的情况:
响应式:显式/直接执行按键处理代码;避免轮询或阻塞延迟的变化 可选性:全局按键是可选的;默认情况下,应用程序正常退出(如果没有操作) 关注点分离:侵入性较小的监听代码;独立于控制台应用程序的核心逻辑运行。
本页上的许多解决方案都涉及轮询控制台。KeyAvailable或在Console.ReadKey上阻塞。虽然。net控制台在这里确实不是很合作,但您可以使用Task。运行以转向更现代的异步侦听模式。
需要注意的主要问题是,默认情况下,你的控制台线程没有设置为Async操作——这意味着,当你从main函数的底部掉出来时,而不是等待Async完成,你的AppDoman和进程将结束。解决这个问题的合适方法是使用Stephen Cleary的AsyncContext在单线程控制台程序中建立完全的Async支持。但对于更简单的情况,比如等待按键,安装一个完整的蹦床可能有点过头了。
下面的例子是用于某种迭代批处理文件的控制台程序。在这种情况下,当程序完成它的工作时,通常它应该退出而不需要按键,然后我们允许一个可选的按键来阻止应用程序退出。我们可以暂停循环来检查内容,也可以继续,或者将暂停作为一个已知的“控制点”,在这个控制点上干净地跳出批处理文件。
static void Main(String[] args)
{
Console.WriteLine("Press any key to prevent exit...");
var tHold = Task.Run(() => Console.ReadKey(true));
// ... do your console app activity ...
if (tHold.IsCompleted)
{
#if false // For the 'hold' state, you can simply halt forever...
Console.WriteLine("Holding.");
Thread.Sleep(Timeout.Infinite);
#else // ...or allow continuing on (to exit)
while (Console.KeyAvailable)
Console.ReadKey(true); // flush/consume any extras
Console.WriteLine("Holding. Press 'Esc' to exit.");
while (Console.ReadKey(true).Key != ConsoleKey.Escape)
;
#endif
}
}
你可以稍微改变一下你的方法——使用Console.ReadKey()来停止你的应用程序,但在后台线程中完成你的工作:
static void Main(string[] args)
{
var myWorker = new MyWorker();
myWorker.DoStuff();
Console.WriteLine("Press any key to stop...");
Console.ReadKey();
}
在myWorker.DoStuff()函数中,您可以在后台线程上调用另一个函数(使用Action<>()或Func<>()是一种简单的方法),然后立即返回。
使用控制台。只有当你知道ReadKey不会被阻塞时,你才会调用ReadKey:
Console.WriteLine("Press ESC to stop");
do {
while (! Console.KeyAvailable) {
// Do something
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
Console.WriteLine("Hello");
var key = Console.ReadKey();
DateTime start = DateTime.Now;
bool gotKey = Console.KeyAvailable;
while ((DateTime.Now - start).TotalSeconds < 2)
{
if (key.Key == ConsoleKey.Escape)
{
Environment.Exit(0);
}
else if (key.Key == ConsoleKey.Enter)
{
break;
}