Listen for key press in .NET console app

后端 未结 9 1339
隐瞒了意图╮
隐瞒了意图╮ 2020-11-22 05:02

How can I continue to run my console application until a key press (like Esc is pressed?)

I\'m assuming its wrapped around a while loop. I don\'t like

相关标签:
9条回答
  • 2020-11-22 05:16

    The shortest way:

    Console.WriteLine("Press ESC to stop");
    
    while (!(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape))
    {
        // do something
    }
    

    Console.ReadKey() is a blocking function, it stops the execution of the program and waits for a key press, but thanks to checking Console.KeyAvailable first, the while loop is not blocked, but running until the Esc is pressed.

    0 讨论(0)
  • 2020-11-22 05:16

    From the video curse Building .NET Console Applications in C# by Jason Roberts at http://www.pluralsight.com

    We could do following to have multiple running process

      static void Main(string[] args)
        {
            Console.CancelKeyPress += (sender, e) =>
            {
    
                Console.WriteLine("Exiting...");
                Environment.Exit(0);
            };
    
            Console.WriteLine("Press ESC to Exit");
    
            var taskKeys = new Task(ReadKeys);
            var taskProcessFiles = new Task(ProcessFiles);
    
            taskKeys.Start();
            taskProcessFiles.Start();
    
            var tasks = new[] { taskKeys };
            Task.WaitAll(tasks);
        }
    
        private static void ProcessFiles()
        {
            var files = Enumerable.Range(1, 100).Select(n => "File" + n + ".txt");
    
            var taskBusy = new Task(BusyIndicator);
            taskBusy.Start();
    
            foreach (var file in files)
            {
                Thread.Sleep(1000);
                Console.WriteLine("Procesing file {0}", file);
            }
        }
    
        private static void BusyIndicator()
        {
            var busy = new ConsoleBusyIndicator();
            busy.UpdateProgress();
        }
    
        private static void ReadKeys()
        {
            ConsoleKeyInfo key = new ConsoleKeyInfo();
    
            while (!Console.KeyAvailable && key.Key != ConsoleKey.Escape)
            {
    
                key = Console.ReadKey(true);
    
                switch (key.Key)
                {
                    case ConsoleKey.UpArrow:
                        Console.WriteLine("UpArrow was pressed");
                        break;
                    case ConsoleKey.DownArrow:
                        Console.WriteLine("DownArrow was pressed");
                        break;
    
                    case ConsoleKey.RightArrow:
                        Console.WriteLine("RightArrow was pressed");
                        break;
    
                    case ConsoleKey.LeftArrow:
                        Console.WriteLine("LeftArrow was pressed");
                        break;
    
                    case ConsoleKey.Escape:
                        break;
    
                    default:
                        if (Console.CapsLock && Console.NumberLock)
                        {
                            Console.WriteLine(key.KeyChar);
                        }
                        break;
                }
            }
        }
    }
    
    internal class ConsoleBusyIndicator
    {
        int _currentBusySymbol;
    
        public char[] BusySymbols { get; set; }
    
        public ConsoleBusyIndicator()
        {
            BusySymbols = new[] { '|', '/', '-', '\\' };
        }
        public void UpdateProgress()
        {
            while (true)
            {
                Thread.Sleep(100);
                var originalX = Console.CursorLeft;
                var originalY = Console.CursorTop;
    
                Console.Write(BusySymbols[_currentBusySymbol]);
    
                _currentBusySymbol++;
    
                if (_currentBusySymbol == BusySymbols.Length)
                {
                    _currentBusySymbol = 0;
                }
    
                Console.SetCursorPosition(originalX, originalY);
            }
        }
    
    0 讨论(0)
  • 2020-11-22 05:16

    According to my experience, in console apps the easiest way to read the last key pressed is as follows (Example with arrow keys):

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

    I use to avoid loops, instead I write the code above within a method, and I call it at the end of both "Method1" and "Method2", so, after executing "Method1" or "Method2", Console.ReadKey().Key is ready to read the keys again.

    0 讨论(0)
  • 2020-11-22 05:17

    You can change your approach slightly - use Console.ReadKey() to stop your app, but do your work in a background thread:

    static void Main(string[] args)
    {
        var myWorker = new MyWorker();
        myWorker.DoStuff();
        Console.WriteLine("Press any key to stop...");
        Console.ReadKey();
    }
    

    In the myWorker.DoStuff() function you would then invoke another function on a background thread (using Action<>() or Func<>() is an easy way to do it), then immediately return.

    0 讨论(0)
  • 2020-11-22 05:17

    Here is an approach for you to do something on a different thread and start listening to the key pressed in a different thread. And the Console will stop its processing when your actual process ends or the user terminates the process by pressing Esc key.

    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;
    
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 05:21

    with below code you can listen SpaceBar pressing , in middle of your console execution and pause until another key is pressed and also listen for EscapeKey for breaking the main loop

    static ConsoleKeyInfo cki = new ConsoleKeyInfo();
    
    
    while(true) {
          if (WaitOrBreak()) break;
          //your main code
    }
    
     private static bool WaitOrBreak(){
            if (Console.KeyAvailable) cki = Console.ReadKey(true);
            if (cki.Key == ConsoleKey.Spacebar)
            {
                Console.Write("waiting..");
                while (Console.KeyAvailable == false)
                {
                    Thread.Sleep(250);Console.Write(".");
                }
                Console.WriteLine();
                Console.ReadKey(true);
                cki = new ConsoleKeyInfo();
            }
            if (cki.Key == ConsoleKey.Escape) return true;
            return false;
        }
    
    0 讨论(0)
提交回复
热议问题