6


I know I can use ReadKey for that but it will freeze the app until user presses a key. Is it possible (in console app) to have some loop running and still be able to react? I can only think of events but not sure how to use them in console. My idea was that the loop would check for input during each iteration.

Ptr
  • 149
  • 1
  • 8
  • Surely you want the app to be in a state of ready to accept user input, so on key press you can do some functionality. Or is this like a press a button to cancel processing?? – jimplode Oct 14 '10 at 08:18
  • Yes but great example is a game - you need to run some loop (enemy movement, whatever) but still register player input – Ptr Oct 14 '10 at 08:22

3 Answers3

8

They way I have done this for my own application was to have a dedicated thread that calls into System.Console.ReadKey(true) and puts the keys pressed (and any other events) into a message queue.

The main thread then services this queue in a loop (in a similar fashion to the main loop in a Win32 application), ensuring that rendering and event processing is all handled on a single thread.

private void StartKeyboardListener()
{
    var thread = new Thread(() => {
                                      while (!this.stopping)
                                      {
                                          ConsoleKeyInfo key = System.Console.ReadKey(true);
                                          this.messageQueue.Enqueue(new KeyboardMessage(key));
                                      }
                                  });

    thread.IsBackground = true;
    thread.Start();
}

private void MessageLoop()
{
    while (!this.stopping)
    {
        Message message = this.messageQueue.Dequeue(DEQUEUE_TIMEOUT);

        if (message != null)
        {
            switch (message.MessageType)
            {
                case MessageType.Keyboard:
                    HandleKeyboardMessage((KeyboardMessage) message);
                    break;
                ...
            }
        }

        Thread.Yield(); // or Thread.Sleep(0)
    }
}
Paul Ruane
  • 37,459
  • 12
  • 63
  • 82
1

Have the loop run in separate thread.

class Program
{
  private static string input;

  public static void Main()
  {
    Thread t = new Thread(new ThreadStart(work));
    input = Console.ReadLine();

  }

  private static void work()
  {
     while (input == null)
     {
       //do stuff....      
     }
  }
}
Itay Karo
  • 17,924
  • 4
  • 40
  • 58
1

Try KeyAvailable property starting with .NET Framework 2 through now (current .NET 6 - including .NET Core). A single thread can process in a loop without being blocked.

// loop start

if (Console.KeyAvailable) // Non-blocking peek
{
   var key = Console.ReadKey(true);
   // process key
}
// continue without stopping

// loop end
Dana Reed
  • 59
  • 1
  • 7