我如何继续运行我的控制台应用程序,直到一个键按下(如Esc按下?)

我假设它环绕着一个while循环。我不喜欢ReadKey,因为它阻塞操作并要求一个键,而不是只是继续听按键。

如何做到这一点呢?


当前回答

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;
    } 

其他回答

下面是一种方法,可以让您在不同的线程上执行某些操作,并开始侦听不同线程中按下的键。当您的实际进程结束或用户按Esc键终止该进程时,控制台将停止其处理。

class SplitAnalyser
{
    public static bool stopProcessor = false;
    public static bool Terminate = false;

    static void Main(string[] args)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine("Split Analyser starts");
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("Press Esc to quit.....");
        Thread MainThread = new Thread(new ThreadStart(startProcess));
        Thread ConsoleKeyListener = new Thread(new ThreadStart(ListerKeyBoardEvent));
        MainThread.Name = "Processor";
        ConsoleKeyListener.Name = "KeyListener";
        MainThread.Start();
        ConsoleKeyListener.Start();

        while (true) 
        {
            if (Terminate)
            {
                Console.WriteLine("Terminating Process...");
                MainThread.Abort();
                ConsoleKeyListener.Abort();
                Thread.Sleep(2000);
                Thread.CurrentThread.Abort();
                return;
            }

            if (stopProcessor)
            {
                Console.WriteLine("Ending Process...");
                MainThread.Abort();
                ConsoleKeyListener.Abort();
                Thread.Sleep(2000);
                Thread.CurrentThread.Abort();
                return;
            }
        } 
    }

    public static void ListerKeyBoardEvent()
    {
        do
        {
            if (Console.ReadKey(true).Key == ConsoleKey.Escape)
            {
                Terminate = true;
            }
        } while (true); 
    }

    public static void startProcess()
    {
        int i = 0;
        while (true)
        {
            if (!stopProcessor && !Terminate)
            {
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("Processing...." + i++);
                Thread.Sleep(3000);
            }
            if(i==10)
                stopProcessor = true;

        }
    }

}

处理一些其他答案不能很好处理的情况:

响应式:显式/直接执行按键处理代码;避免轮询或阻塞延迟的变化 可选性:全局按键是可选的;默认情况下,应用程序正常退出(如果没有操作) 关注点分离:侵入性较小的监听代码;独立于控制台应用程序的核心逻辑运行。


本页上的许多解决方案都涉及轮询控制台。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
    }
}

根据我的经验,在控制台应用中,读取最后按下的键的最简单方法如下(以箭头键为例):

ConsoleKey readKey = Console.ReadKey ().Key;
if (readKey == ConsoleKey.LeftArrow) {
    <Method1> ();  //Do something
} else if (readKey == ConsoleKey.RightArrow) {
    <Method2> ();  //Do something
}

我用来避免循环,而不是我在一个方法中写上面的代码,我在“Method1”和“Method2”的末尾调用它,所以,在执行“Method1”或“Method2”后,Console.ReadKey()。键已准备好再次读取键。

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;
    } 

如果你正在使用Visual Studio,那么你可以在调试菜单中使用“开始不调试”。

它会自动写“按任意键继续…”到控制台完成应用程序后,它会让控制台为您打开,直到按下一个键。