How to add a Timeout to Console.ReadLine()?

后端 未结 30 2565
耶瑟儿~
耶瑟儿~ 2020-11-22 04:57

I have a console app in which I want to give the user x seconds to respond to the prompt. If no input is made after a certain period of time, program logic should

30条回答
  •  感情败类
    2020-11-22 05:44

    I had a unique situation of having a Windows Application (Windows Service). When running the program interactively Environment.IsInteractive (VS Debugger or from cmd.exe), I used AttachConsole/AllocConsole to get my stdin/stdout. To keep the process from ending while the work was being done, the UI Thread calls Console.ReadKey(false). I wanted to cancel the waiting the UI thread was doing from another thread, so I came up with a modification to the solution by @JSquaredD.

    using System;
    using System.Diagnostics;
    
    internal class PressAnyKey
    {
      private static Thread inputThread;
      private static AutoResetEvent getInput;
      private static AutoResetEvent gotInput;
      private static CancellationTokenSource cancellationtoken;
    
      static PressAnyKey()
      {
        // Static Constructor called when WaitOne is called (technically Cancel too, but who cares)
        getInput = new AutoResetEvent(false);
        gotInput = new AutoResetEvent(false);
        inputThread = new Thread(ReaderThread);
        inputThread.IsBackground = true;
        inputThread.Name = "PressAnyKey";
        inputThread.Start();
      }
    
      private static void ReaderThread()
      {
        while (true)
        {
          // ReaderThread waits until PressAnyKey is called
          getInput.WaitOne();
          // Get here 
          // Inner loop used when a caller uses PressAnyKey
          while (!Console.KeyAvailable && !cancellationtoken.IsCancellationRequested)
          {
            Thread.Sleep(50);
          }
          // Release the thread that called PressAnyKey
          gotInput.Set();
        }
      }
    
      /// 
      /// Signals the thread that called WaitOne should be allowed to continue
      /// 
      public static void Cancel()
      {
        // Trigger the alternate ending condition to the inner loop in ReaderThread
        if(cancellationtoken== null) throw new InvalidOperationException("Must call WaitOne before Cancelling");
        cancellationtoken.Cancel();
      }
    
      /// 
      /// Wait until a key is pressed or  is called by another thread
      /// 
      public static void WaitOne()
      {
        if(cancellationtoken==null || cancellationtoken.IsCancellationRequested) throw new InvalidOperationException("Must cancel a pending wait");
        cancellationtoken = new CancellationTokenSource();
        // Release the reader thread
        getInput.Set();
        // Calling thread will wait here indefiniately 
        // until a key is pressed, or Cancel is called
        gotInput.WaitOne();
      }    
    }
    

提交回复
热议问题