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

后端 未结 30 3145
耶瑟儿~
耶瑟儿~ 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:58

    Here is a solution that uses Console.KeyAvailable. These are blocking calls, but it should be fairly trivial to call them asynchronously via the TPL if desired. I used the standard cancellation mechanisms to make it easy to wire in with the Task Asynchronous Pattern and all that good stuff.

    public static class ConsoleEx
    {
      public static string ReadLine(TimeSpan timeout)
      {
        var cts = new CancellationTokenSource();
        return ReadLine(timeout, cts.Token);
      }
    
      public static string ReadLine(TimeSpan timeout, CancellationToken cancellation)
      {
        string line = "";
        DateTime latest = DateTime.UtcNow.Add(timeout);
        do
        {
            cancellation.ThrowIfCancellationRequested();
            if (Console.KeyAvailable)
            {
                ConsoleKeyInfo cki = Console.ReadKey();
                if (cki.Key == ConsoleKey.Enter)
                {
                    return line;
                }
                else
                {
                    line += cki.KeyChar;
                }
            }
            Thread.Sleep(1);
        }
        while (DateTime.UtcNow < latest);
        return null;
      }
    }
    

    There are some disadvantages with this.

    • You do not get the standard navigation features that ReadLine provides (up/down arrow scrolling, etc.).
    • This injects '\0' characters into input if a special key is press (F1, PrtScn, etc.). You could easily filter them out by modifying the code though.

提交回复
热议问题