<p>I have a console app in which I want to give the user <em>x</em> seconds to respond to the prompt.  If no input is made after a certain period of time, program logic should continue.  We assume a timeout means empty response.</p>

<p>What is the most straightforward way of approaching this?</p>

[{'answer_id': 57639, 'author': 'GEOCHET', 'author_id': 5640, 'author_profile': 'https://Stackoverflow.com/users/5640', 'pm_score': 3, 'selected': False, 'text': '<p>I think you will need to make a secondary thread and poll for a key on the console. I know of no built in way to accomplish this.</p>\n'}, {'answer_id': 57655, 'author': 'Gulzar Nazim', 'author_id': 4337, 'author_profile': 'https://Stackoverflow.com/users/4337', 'pm_score': 5, 'selected': False, 'text': '<p>Will this approach using <a href="http://msdn.microsoft.com/en-us/library/system.console.keyavailable.aspx" rel="noreferrer">Console.KeyAvailable</a> help?</p>\n\n<pre><code>class Sample \n{\n    public static void Main() \n    {\n    ConsoleKeyInfo cki = new ConsoleKeyInfo();\n\n    do {\n        Console.WriteLine("\\nPress a key to display; press the \'x\' key to quit.");\n\n// Your code could perform some useful task in the following loop. However, \n// for the sake of this example we\'ll merely pause for a quarter second.\n\n        while (Console.KeyAvailable == false)\n            Thread.Sleep(250); // Loop until input is entered.\n        cki = Console.ReadKey(true);\n        Console.WriteLine("You pressed the \'{0}\' key.", cki.Key);\n        } while(cki.Key != ConsoleKey.X);\n    }\n}\n</code></pre>\n'}, {'answer_id': 57686, 'author': 'Eric', 'author_id': 4540, 'author_profile': 'https://Stackoverflow.com/users/4540', 'pm_score': 3, 'selected': False, 'text': '<p>One way or another you do need a second thread.  You could use asynchronous IO to avoid declaring your own:</p>\n\n<ul>\n<li>declare a ManualResetEvent, call it "evt"</li>\n<li>call System.Console.OpenStandardInput to get the input stream.  Specify a callback method that will store its data and set evt.</li>\n<li>call that stream\'s BeginRead method to start an asynchronous read operation</li>\n<li>then enter a timed wait on a ManualResetEvent</li>\n<li>if the wait times out, then cancel the read</li>\n</ul>\n\n<p>If the read returns data, set the event and your main thread will continue, otherwise you\'ll continue after the timeout.</p>\n'}, {'answer_id': 57692, 'author': 'Joel Coehoorn', 'author_id': 3043, 'author_profile': 'https://Stackoverflow.com/users/3043', 'pm_score': 0, 'selected': False, 'text': '<p>Another cheap way to get a 2nd thread is to wrap it in a delegate.</p>\n'}, {'answer_id': 57711, 'author': 'Jesse C. Slicer', 'author_id': 3312, 'author_profile': 'https://Stackoverflow.com/users/3312', 'pm_score': 2, 'selected': False, 'text': '<p><strong>EDIT</strong>: fixed the problem by having the actual work be done in a separate process and killing that process if it times out.  See below for details.  Whew!</p>\n\n<p>Just gave this a run and it seemed to work nicely.  My coworker had a version which used a Thread object, but I find the BeginInvoke() method of delegate types to be a bit more elegant.</p>\n\n<pre><code>namespace TimedReadLine\n{\n   public static class Console\n   {\n      private delegate string ReadLineInvoker();\n\n      public static string ReadLine(int timeout)\n      {\n         return ReadLine(timeout, null);\n      }\n\n      public static string ReadLine(int timeout, string @default)\n      {\n         using (var process = new System.Diagnostics.Process\n         {\n            StartInfo =\n            {\n               FileName = "ReadLine.exe",\n               RedirectStandardOutput = true,\n               UseShellExecute = false\n            }\n         })\n         {\n            process.Start();\n\n            var rli = new ReadLineInvoker(process.StandardOutput.ReadLine);\n            var iar = rli.BeginInvoke(null, null);\n\n            if (!iar.AsyncWaitHandle.WaitOne(new System.TimeSpan(0, 0, timeout)))\n            {\n               process.Kill();\n               return @default;\n            }\n\n            return rli.EndInvoke(iar);\n         }\n      }\n   }\n}\n</code></pre>\n\n<p>The ReadLine.exe project is a very simple one which has one class which looks like so:</p>\n\n<pre><code>namespace ReadLine\n{\n   internal static class Program\n   {\n      private static void Main()\n      {\n         System.Console.WriteLine(System.Console.ReadLine());\n      }\n   }\n}\n</code></pre>\n'}, {'answer_id': 57775, 'author': 'Brannon', 'author_id': 5745, 'author_profile': 'https://Stackoverflow.com/users/5745', 'pm_score': 3, 'selected': False, 'text': '<p>Calling Console.ReadLine() in the delegate is bad because if the user doesn\'t hit \'enter\' then that call will never return.  The thread executing the delegate will be blocked until the user hits \'enter\', with no way to cancel it.</p>\n\n<p>Issuing a sequence of these calls will not behave as you would expect.  Consider the following (using the example Console class from above):</p>\n\n<pre><code>System.Console.WriteLine("Enter your first name [John]:");\n\nstring firstName = Console.ReadLine(5, "John");\n\nSystem.Console.WriteLine("Enter your last name [Doe]:");\n\nstring lastName = Console.ReadLine(5, "Doe");\n</code></pre>\n\n<p>The user lets the timeout expire for the first prompt, then enters a value for the second prompt.  Both firstName and lastName will contain the default values. When the user hits \'enter\', the <strong>first</strong> ReadLine call will complete, but the code has abandonded that call and essentially discarded the result.  The <strong>second</strong> ReadLine call will continue to block, the timeout will eventually expire and the value returned will again be the default.</p>\n\n<p>BTW- There is a bug in the code above.  By calling waitHandle.Close() you close the event out from under the worker thread.  If the user hits \'enter\' after the timeout expires, the worker thread will attempt to signal the event which throws an ObjectDisposedException.  The exception is thrown from the worker thread, and if you haven\'t setup an unhandled exception handler your process will terminate.</p>\n'}, {'answer_id': 231333, 'author': 'Ryan', 'author_id': 29762, 'author_profile': 'https://Stackoverflow.com/users/29762', 'pm_score': 2, 'selected': False, 'text': '<p>I may be reading too much into the question, but I am assuming the wait would be similar to the boot menu where it waits 15 seconds unless you press a key.  You could either use (1) a blocking function or (2) you could use a thread, an event, and a timer. The event would act as a \'continue\' and would block until either the timer expired or a key was pressed.</p>\n\n<p>Pseudo-code for (1) would be:</p>\n\n<pre><code>// Get configurable wait time\nTimeSpan waitTime = TimeSpan.FromSeconds(15.0);\nint configWaitTimeSec;\nif (int.TryParse(ConfigManager.AppSetting["DefaultWaitTime"], out configWaitTimeSec))\n    waitTime = TimeSpan.FromSeconds(configWaitTimeSec);\n\nbool keyPressed = false;\nDateTime expireTime = DateTime.Now + waitTime;\n\n// Timer and key processor\nConsoleKeyInfo cki;\n// EDIT: adding a missing ! below\nwhile (!keyPressed &amp;&amp; (DateTime.Now &lt; expireTime))\n{\n    if (Console.KeyAvailable)\n    {\n        cki = Console.ReadKey(true);\n        // TODO: Process key\n        keyPressed = true;\n    }\n    Thread.Sleep(10);\n}\n</code></pre>\n'}, {'answer_id': 885542, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 0, 'selected': False, 'text': "<p>Example implementation of Eric's post above.  This particular example was used to read information that was passed to a console app via pipe:</p>\n\n<pre><code> using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Threading;\n\nnamespace PipedInfo\n{\n    class Program\n    {\n        static void Main(string[] args)\n        {\n            StreamReader buffer = ReadPipedInfo();\n\n            Console.WriteLine(buffer.ReadToEnd());\n        }\n\n        #region ReadPipedInfo\n        public static StreamReader ReadPipedInfo()\n        {\n            //call with a default value of 5 milliseconds\n            return ReadPipedInfo(5);\n        }\n\n        public static StreamReader ReadPipedInfo(int waitTimeInMilliseconds)\n        {\n            //allocate the class we're going to callback to\n            ReadPipedInfoCallback callbackClass = new ReadPipedInfoCallback();\n\n            //to indicate read complete or timeout\n            AutoResetEvent readCompleteEvent = new AutoResetEvent(false);\n\n            //open the StdIn so that we can read against it asynchronously\n            Stream stdIn = Console.OpenStandardInput();\n\n            //allocate a one-byte buffer, we're going to read off the stream one byte at a time\n            byte[] singleByteBuffer = new byte[1];\n\n            //allocate a list of an arbitary size to store the read bytes\n            List&lt;byte&gt; byteStorage = new List&lt;byte&gt;(4096);\n\n            IAsyncResult asyncRead = null;\n            int readLength = 0; //the bytes we have successfully read\n\n            do\n            {\n                //perform the read and wait until it finishes, unless it's already finished\n                asyncRead = stdIn.BeginRead(singleByteBuffer, 0, singleByteBuffer.Length, new AsyncCallback(callbackClass.ReadCallback), readCompleteEvent);\n                if (!asyncRead.CompletedSynchronously)\n                    readCompleteEvent.WaitOne(waitTimeInMilliseconds);\n\n                //end the async call, one way or another\n\n                //if our read succeeded we store the byte we read\n                if (asyncRead.IsCompleted)\n                {\n                    readLength = stdIn.EndRead(asyncRead);\n                    if (readLength &gt; 0)\n                        byteStorage.Add(singleByteBuffer[0]);\n                }\n\n            } while (asyncRead.IsCompleted &amp;&amp; readLength &gt; 0);\n            //we keep reading until we fail or read nothing\n\n            //return results, if we read zero bytes the buffer will return empty\n            return new StreamReader(new MemoryStream(byteStorage.ToArray(), 0, byteStorage.Count));\n        }\n\n        private class ReadPipedInfoCallback\n        {\n            public void ReadCallback(IAsyncResult asyncResult)\n            {\n                //pull the user-defined variable and strobe the event, the read finished successfully\n                AutoResetEvent readCompleteEvent = asyncResult.AsyncState as AutoResetEvent;\n                readCompleteEvent.Set();\n            }\n        }\n        #endregion ReadPipedInfo\n    }\n}\n</code></pre>\n"}, {'answer_id': 2041489, 'author': 'gp.', 'author_id': 247843, 'author_profile': 'https://Stackoverflow.com/users/247843', 'pm_score': 5, 'selected': False, 'text': '<pre><code>string ReadLine(int timeoutms)\n{\n    ReadLineDelegate d = Console.ReadLine;\n    IAsyncResult result = d.BeginInvoke(null, null);\n    result.AsyncWaitHandle.WaitOne(timeoutms);//timeout e.g. 15000 for 15 secs\n    if (result.IsCompleted)\n    {\n        string resultstr = d.EndInvoke(result);\n        Console.WriteLine("Read: " + resultstr);\n        return resultstr;\n    }\n    else\n    {\n        Console.WriteLine("Timed out!");\n        throw new TimedoutException("Timed Out!");\n    }\n}\n\ndelegate string ReadLineDelegate();\n</code></pre>\n'}, {'answer_id': 2282672, 'author': 'mphair', 'author_id': 191299, 'author_profile': 'https://Stackoverflow.com/users/191299', 'pm_score': 1, 'selected': False, 'text': '<p>Simple threading example to solve this</p>\n\n<pre><code>Thread readKeyThread = new Thread(ReadKeyMethod);\nstatic ConsoleKeyInfo cki = null;\n\nvoid Main()\n{\n    readKeyThread.Start();\n    bool keyEntered = false;\n    for(int ii = 0; ii &lt; 10; ii++)\n    {\n        Thread.Sleep(1000);\n        if(readKeyThread.ThreadState == ThreadState.Stopped)\n            keyEntered = true;\n    }\n    if(keyEntered)\n    { //do your stuff for a key entered\n    }\n}\n\nvoid ReadKeyMethod()\n{\n    cki = Console.ReadKey();\n}\n</code></pre>\n\n<p>or a static string up top for getting an entire line.</p>\n'}, {'answer_id': 2967469, 'author': 'Jamie Kitson', 'author_id': 139560, 'author_profile': 'https://Stackoverflow.com/users/139560', 'pm_score': 2, 'selected': False, 'text': '<p>I can\'t comment on Gulzar\'s post unfortunately, but here\'s a fuller example:</p>\n\n<pre><code>            while (Console.KeyAvailable == false)\n            {\n                Thread.Sleep(250);\n                i++;\n                if (i &gt; 3)\n                    throw new Exception("Timedout waiting for input.");\n            }\n            input = Console.ReadLine();\n</code></pre>\n'}, {'answer_id': 2974065, 'author': 'Sasha', 'author_id': 197897, 'author_profile': 'https://Stackoverflow.com/users/197897', 'pm_score': 1, 'selected': False, 'text': '<p>Im my case this work fine:</p>\n\n<pre><code>public static ManualResetEvent evtToWait = new ManualResetEvent(false);\n\nprivate static void ReadDataFromConsole( object state )\n{\n    Console.WriteLine("Enter \\"x\\" to exit or wait for 5 seconds.");\n\n    while (Console.ReadKey().KeyChar != \'x\')\n    {\n        Console.Out.WriteLine("");\n        Console.Out.WriteLine("Enter again!");\n    }\n\n    evtToWait.Set();\n}\n\nstatic void Main(string[] args)\n{\n        Thread status = new Thread(ReadDataFromConsole);\n        status.Start();\n\n        evtToWait = new ManualResetEvent(false);\n\n        evtToWait.WaitOne(5000); // wait for evtToWait.Set() or timeOut\n\n        status.Abort(); // exit anyway\n        return;\n}\n</code></pre>\n'}, {'answer_id': 3591551, 'author': 'Glenn Slayden', 'author_id': 147511, 'author_profile': 'https://Stackoverflow.com/users/147511', 'pm_score': 3, 'selected': False, 'text': "<pre><code>// Wait for 'Enter' to be pressed or 5 seconds to elapse\nusing (Stream s = Console.OpenStandardInput())\n{\n    ManualResetEvent stop_waiting = new ManualResetEvent(false);\n    s.BeginRead(new Byte[1], 0, 1, ar =&gt; stop_waiting.Set(), null);\n\n    // ...do anything else, or simply...\n\n    stop_waiting.WaitOne(5000);\n    // If desired, other threads could also set 'stop_waiting' \n    // Disposing the stream cancels the async read operation. It can be\n    // re-opened if needed.\n}\n</code></pre>\n"}, {'answer_id': 7318974, 'author': 'Contango', 'author_id': 107409, 'author_profile': 'https://Stackoverflow.com/users/107409', 'pm_score': 0, 'selected': False, 'text': '<pre><code>string readline = "?";\nThreadPool.QueueUserWorkItem(\n    delegate\n    {\n        readline = Console.ReadLine();\n    }\n);\ndo\n{\n    Thread.Sleep(100);\n} while (readline == "?");\n</code></pre>\n\n<p>Note that if you go down the "Console.ReadKey" route, you lose some of the cool features of ReadLine, namely:</p>\n\n<ul>\n<li>Support for delete, backspace, arrow keys, etc.</li>\n<li>The ability to press the "up" key and repeat the last command (this comes in very handy if you implement a background debugging console that gets a lot of use).</li>\n</ul>\n\n<p>To add a timeout, alter the while loop to suit.</p>\n'}, {'answer_id': 7664463, 'author': 'user980750', 'author_id': 980750, 'author_profile': 'https://Stackoverflow.com/users/980750', 'pm_score': 4, 'selected': False, 'text': '<p>This worked for me.</p>\n<pre><code>ConsoleKeyInfo k = new ConsoleKeyInfo();\nConsole.WriteLine(&quot;Press any key in the next 5 seconds.&quot;);\nfor (int cnt = 5; cnt &gt; 0; cnt--)\n  {\n    if (Console.KeyAvailable)\n      {\n        k = Console.ReadKey();\n        break;\n      }\n    else\n     {\n       Console.WriteLine(cnt.ToString());\n       System.Threading.Thread.Sleep(1000);\n     }\n }\nConsole.WriteLine(&quot;The key pressed was &quot; + k.Key);\n</code></pre>\n'}, {'answer_id': 9016896, 'author': 'Contango', 'author_id': 107409, 'author_profile': 'https://Stackoverflow.com/users/107409', 'pm_score': 3, 'selected': False, 'text': '<p>I struggled with this problem for 5 months before I found an solution that works perfectly in an enterprise setting.</p>\n\n<p>The problem with most of the solutions so far is that they rely on something other than Console.ReadLine(), and Console.ReadLine() has a lot of advantages:</p>\n\n<ul>\n<li>Support for delete, backspace, arrow keys, etc.</li>\n<li>The ability to press the "up" key and repeat the last command (this comes in very handy if you implement a background debugging console that gets a lot of use).</li>\n</ul>\n\n<p>My solution is as follows:</p>\n\n<ol>\n<li>Spawn a <strong>separate thread</strong> to handle the user input using Console.ReadLine().</li>\n<li>After the timeout period, unblock Console.ReadLine() by sending an [enter] key into the current console window, using <a href="http://inputsimulator.codeplex.com/" rel="nofollow noreferrer">http://inputsimulator.codeplex.com/</a>.</li>\n</ol>\n\n<p>Sample code:</p>\n\n<pre><code> InputSimulator.SimulateKeyPress(VirtualKeyCode.RETURN);\n</code></pre>\n\n<p>More information on this technique, including the correct technique to abort a thread that uses Console.ReadLine:</p>\n\n<p><a href="https://stackoverflow.com/questions/9016087/net-call-to-send-enter-keystroke-into-the-current-process-which-is-a-console">.NET call to send [enter] keystroke into the current process, which is a console app?</a></p>\n\n<p><a href="https://stackoverflow.com/questions/8984838/how-to-abort-another-thread-in-net-when-said-thread-is-executing-console-readl">How to abort another thread in .NET, when said thread is executing Console.ReadLine?</a></p>\n'}, {'answer_id': 16503766, 'author': 'John Atac', 'author_id': 2374141, 'author_profile': 'https://Stackoverflow.com/users/2374141', 'pm_score': 1, 'selected': False, 'text': "<p>Isn't this nice and short?</p>\n\n<pre><code>if (SpinWait.SpinUntil(() =&gt; Console.KeyAvailable, millisecondsTimeout))\n{\n    ConsoleKeyInfo keyInfo = Console.ReadKey();\n\n    // Handle keyInfo value here...\n}\n</code></pre>\n"}, {'answer_id': 17627972, 'author': 'mikemay', 'author_id': 96167, 'author_profile': 'https://Stackoverflow.com/users/96167', 'pm_score': 1, 'selected': False, 'text': '<p>This is a fuller example of Glen Slayden\'s solution.  I happended to make this when building a test case for another problem.  It uses asynchronous I/O and a manual reset event.</p>\n\n<pre><code>public static void Main() {\n    bool readInProgress = false;\n    System.IAsyncResult result = null;\n    var stop_waiting = new System.Threading.ManualResetEvent(false);\n    byte[] buffer = new byte[256];\n    var s = System.Console.OpenStandardInput();\n    while (true) {\n        if (!readInProgress) {\n            readInProgress = true;\n            result = s.BeginRead(buffer, 0, buffer.Length\n              , ar =&gt; stop_waiting.Set(), null);\n\n        }\n        bool signaled = true;\n        if (!result.IsCompleted) {\n            stop_waiting.Reset();\n            signaled = stop_waiting.WaitOne(5000);\n        }\n        else {\n            signaled = true;\n        }\n        if (signaled) {\n            readInProgress = false;\n            int numBytes = s.EndRead(result);\n            string text = System.Text.Encoding.UTF8.GetString(buffer\n              , 0, numBytes);\n            System.Console.Out.Write(string.Format(\n              "Thank you for typing: {0}", text));\n        }\n        else {\n            System.Console.Out.WriteLine("oy, type something!");\n        }\n    }\n</code></pre>\n'}, {'answer_id': 17946497, 'author': 'David Kirkland', 'author_id': 41621, 'author_profile': 'https://Stackoverflow.com/users/41621', 'pm_score': 0, 'selected': False, 'text': '<p>Please don\'t hate me for adding another solution to the plethora of existing answers! This works for Console.ReadKey(), but could easily be modified to work with ReadLine(), etc.</p>\n\n<p>As the "Console.Read" methods are blocking, it\'s necessary to "<a href="https://stackoverflow.com/questions/9479573/interrupt-console-readline">nudge</a>" the StdIn stream to cancel the read.</p>\n\n<p>Calling syntax:<br></p>\n\n<pre><code>ConsoleKeyInfo keyInfo;\nbool keyPressed = AsyncConsole.ReadKey(500, out keyInfo);\n// where 500 is the timeout\n</code></pre>\n\n<p>Code:</p>\n\n<pre><code>public class AsyncConsole // not thread safe\n{\n    private static readonly Lazy&lt;AsyncConsole&gt; Instance =\n        new Lazy&lt;AsyncConsole&gt;();\n\n    private bool _keyPressed;\n    private ConsoleKeyInfo _keyInfo;\n\n    private bool DoReadKey(\n        int millisecondsTimeout,\n        out ConsoleKeyInfo keyInfo)\n    {\n        _keyPressed = false;\n        _keyInfo = new ConsoleKeyInfo();\n\n        Thread readKeyThread = new Thread(ReadKeyThread);\n        readKeyThread.IsBackground = false;\n        readKeyThread.Start();\n\n        Thread.Sleep(millisecondsTimeout);\n\n        if (readKeyThread.IsAlive)\n        {\n            try\n            {\n                IntPtr stdin = GetStdHandle(StdHandle.StdIn);\n                CloseHandle(stdin);\n                readKeyThread.Join();\n            }\n            catch { }\n        }\n\n        readKeyThread = null;\n\n        keyInfo = _keyInfo;\n        return _keyPressed;\n    }\n\n    private void ReadKeyThread()\n    {\n        try\n        {\n            _keyInfo = Console.ReadKey();\n            _keyPressed = true;\n        }\n        catch (InvalidOperationException) { }\n    }\n\n    public static bool ReadKey(\n        int millisecondsTimeout,\n        out ConsoleKeyInfo keyInfo)\n    {\n        return Instance.Value.DoReadKey(millisecondsTimeout, out keyInfo);\n    }\n\n    private enum StdHandle { StdIn = -10, StdOut = -11, StdErr = -12 };\n\n    [DllImport("kernel32.dll")]\n    private static extern IntPtr GetStdHandle(StdHandle std);\n\n    [DllImport("kernel32.dll")]\n    private static extern bool CloseHandle(IntPtr hdl);\n}\n</code></pre>\n'}, {'answer_id': 18342182, 'author': 'JSQuareD', 'author_id': 1370541, 'author_profile': 'https://Stackoverflow.com/users/1370541', 'pm_score': 8, 'selected': True, 'text': '<p>I\'m surprised to learn that after 5 years, all of the answers still suffer from one or more of the following problems:</p>\n\n<ul>\n<li>A function other than ReadLine is used, causing loss of functionality. (Delete/backspace/up-key for previous input).</li>\n<li>Function behaves badly when invoked multiple times (spawning multiple threads, many hanging ReadLine\'s, or otherwise unexpected behavior).</li>\n<li>Function relies on a busy-wait. Which is a horrible waste since the wait is expected to run anywhere from a number of seconds up to the timeout, which might be multiple minutes. A busy-wait which runs for such an ammount of time is a horrible suck of resources, which is especially bad in a multithreading scenario. If the busy-wait is modified with a sleep this has a negative effect on responsiveness, although I admit that this is probably not a huge problem.</li>\n</ul>\n\n<p>I believe my solution will solve the original problem without suffering from any of the above problems:</p>\n\n<pre><code>class Reader {\n  private static Thread inputThread;\n  private static AutoResetEvent getInput, gotInput;\n  private static string input;\n\n  static Reader() {\n    getInput = new AutoResetEvent(false);\n    gotInput = new AutoResetEvent(false);\n    inputThread = new Thread(reader);\n    inputThread.IsBackground = true;\n    inputThread.Start();\n  }\n\n  private static void reader() {\n    while (true) {\n      getInput.WaitOne();\n      input = Console.ReadLine();\n      gotInput.Set();\n    }\n  }\n\n  // omit the parameter to read a line without a timeout\n  public static string ReadLine(int timeOutMillisecs = Timeout.Infinite) {\n    getInput.Set();\n    bool success = gotInput.WaitOne(timeOutMillisecs);\n    if (success)\n      return input;\n    else\n      throw new TimeoutException("User did not provide input within the timelimit.");\n  }\n}\n</code></pre>\n\n<p>Calling is, of course, very easy:</p>\n\n<pre><code>try {\n  Console.WriteLine("Please enter your name within the next 5 seconds.");\n  string name = Reader.ReadLine(5000);\n  Console.WriteLine("Hello, {0}!", name);\n} catch (TimeoutException) {\n  Console.WriteLine("Sorry, you waited too long.");\n}\n</code></pre>\n\n<p>Alternatively, you can use the <code>TryXX(out)</code> convention, as shmueli suggested:</p>\n\n<pre><code>  public static bool TryReadLine(out string line, int timeOutMillisecs = Timeout.Infinite) {\n    getInput.Set();\n    bool success = gotInput.WaitOne(timeOutMillisecs);\n    if (success)\n      line = input;\n    else\n      line = null;\n    return success;\n  }\n</code></pre>\n\n<p>Which is called as follows:</p>\n\n<pre><code>Console.WriteLine("Please enter your name within the next 5 seconds.");\nstring name;\nbool success = Reader.TryReadLine(out name, 5000);\nif (!success)\n  Console.WriteLine("Sorry, you waited too long.");\nelse\n  Console.WriteLine("Hello, {0}!", name);\n</code></pre>\n\n<p>In both cases, you cannot mix calls to <code>Reader</code> with normal <code>Console.ReadLine</code> calls: if the <code>Reader</code> times out, there will be a hanging <code>ReadLine</code> call. Instead, if you want to have a normal (non-timed) <code>ReadLine</code> call, just use the <code>Reader</code> and omit the timeout, so that it defaults to an infinite timeout.</p>\n\n<p>So how about those problems of the other solutions I mentioned?</p>\n\n<ul>\n<li>As you can see, ReadLine is used, avoiding the first problem.</li>\n<li>The function behaves properly when invoked multiple times. Regardless of whether a timeout occurs or not, only one background thread will ever be running and only at most one call to ReadLine will ever be active. Calling the function will always result in the latest input, or in a timeout, and the user won\'t have to hit enter more than once to submit his input.</li>\n<li>And, obviously, the function does not rely on a busy-wait. Instead it uses proper multithreading techniques to prevent wasting resources.</li>\n</ul>\n\n<p>The only problem that I foresee with this solution is that it is not thread-safe. However, multiple threads can\'t really ask the user for input at the same time, so synchronization should be happening before making a call to <code>Reader.ReadLine</code> anyway.</p>\n'}, {'answer_id': 19321114, 'author': 'Brian Gideon', 'author_id': 158779, 'author_profile': 'https://Stackoverflow.com/users/158779', 'pm_score': 0, 'selected': False, 'text': '<p>Here is a solution that uses <code>Console.KeyAvailable</code>. 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.</p>\n\n<pre><code>public static class ConsoleEx\n{\n  public static string ReadLine(TimeSpan timeout)\n  {\n    var cts = new CancellationTokenSource();\n    return ReadLine(timeout, cts.Token);\n  }\n\n  public static string ReadLine(TimeSpan timeout, CancellationToken cancellation)\n  {\n    string line = "";\n    DateTime latest = DateTime.UtcNow.Add(timeout);\n    do\n    {\n        cancellation.ThrowIfCancellationRequested();\n        if (Console.KeyAvailable)\n        {\n            ConsoleKeyInfo cki = Console.ReadKey();\n            if (cki.Key == ConsoleKey.Enter)\n            {\n                return line;\n            }\n            else\n            {\n                line += cki.KeyChar;\n            }\n        }\n        Thread.Sleep(1);\n    }\n    while (DateTime.UtcNow &lt; latest);\n    return null;\n  }\n}\n</code></pre>\n\n<p>There are some disadvantages with this. </p>\n\n<ul>\n<li>You do not get the standard navigation features that <code>ReadLine</code> provides (up/down arrow scrolling, etc.).</li>\n<li>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.</li>\n</ul>\n'}, {'answer_id': 20631955, 'author': 'Frank Rem', 'author_id': 450467, 'author_profile': 'https://Stackoverflow.com/users/450467', 'pm_score': 0, 'selected': False, 'text': '<p>Ended up here because a duplicate question was asked. I came up with the following solution which looks straightforward. I am sure it has some drawbacks I missed. </p>\n\n<pre><code>static void Main(string[] args)\n{\n    Console.WriteLine("Hit q to continue or wait 10 seconds.");\n\n    Task task = Task.Factory.StartNew(() =&gt; loop());\n\n    Console.WriteLine("Started waiting");\n    task.Wait(10000);\n    Console.WriteLine("Stopped waiting");\n}\n\nstatic void loop()\n{\n    while (true)\n    {\n        if (\'q\' == Console.ReadKey().KeyChar) break;\n    }\n}\n</code></pre>\n'}, {'answer_id': 26184541, 'author': 'Tono Nam', 'author_id': 637142, 'author_profile': 'https://Stackoverflow.com/users/637142', 'pm_score': 0, 'selected': False, 'text': '<p>I came to this answer and end up doing:</p>\n\n<pre><code>    /// &lt;summary&gt;\n    /// Reads Line from console with timeout. \n    /// &lt;/summary&gt;\n    /// &lt;exception cref="System.TimeoutException"&gt;If user does not enter line in the specified time.&lt;/exception&gt;\n    /// &lt;param name="timeout"&gt;Time to wait in milliseconds. Negative value will wait forever.&lt;/param&gt;        \n    /// &lt;returns&gt;&lt;/returns&gt;        \n    public static string ReadLine(int timeout = -1)\n    {\n        ConsoleKeyInfo cki = new ConsoleKeyInfo();\n        StringBuilder sb = new StringBuilder();\n\n        // if user does not want to spesify a timeout\n        if (timeout &lt; 0)\n            return Console.ReadLine();\n\n        int counter = 0;\n\n        while (true)\n        {\n            while (Console.KeyAvailable == false)\n            {\n                counter++;\n                Thread.Sleep(1);\n                if (counter &gt; timeout)\n                    throw new System.TimeoutException("Line was not entered in timeout specified");\n            }\n\n            cki = Console.ReadKey(false);\n\n            if (cki.Key == ConsoleKey.Enter)\n            {\n                Console.WriteLine();\n                return sb.ToString();\n            }\n            else\n                sb.Append(cki.KeyChar);                \n        }            \n    }\n</code></pre>\n'}, {'answer_id': 31089330, 'author': 'cprcrack', 'author_id': 423171, 'author_profile': 'https://Stackoverflow.com/users/423171', 'pm_score': 0, 'selected': False, 'text': '<p>A simple example using <code>Console.KeyAvailable</code>:</p>\n\n<pre><code>Console.WriteLine("Press any key during the next 2 seconds...");\nThread.Sleep(2000);\nif (Console.KeyAvailable)\n{\n    Console.WriteLine("Key pressed");\n}\nelse\n{\n    Console.WriteLine("You were too slow");\n}\n</code></pre>\n'}, {'answer_id': 34749067, 'author': 'StevoInco', 'author_id': 1812688, 'author_profile': 'https://Stackoverflow.com/users/1812688', 'pm_score': 2, 'selected': False, 'text': '<p>.NET 4 makes this incredibly simple using Tasks. </p>\n\n<p>First, build your helper:</p>\n\n<pre><code>   Private Function AskUser() As String\n      Console.Write("Answer my question: ")\n      Return Console.ReadLine()\n   End Function\n</code></pre>\n\n<p>Second, execute with a task and wait:</p>\n\n<pre><code>      Dim askTask As Task(Of String) = New TaskFactory().StartNew(Function() AskUser())\n      askTask.Wait(TimeSpan.FromSeconds(30))\n      If Not askTask.IsCompleted Then\n         Console.WriteLine("User failed to respond.")\n      Else\n         Console.WriteLine(String.Format("You responded, \'{0}\'.", askTask.Result))\n      End If\n</code></pre>\n\n<p>There\'s no trying to recreate ReadLine functionality or performing other perilous hacks to get this working. Tasks let us solve the question in a very natural way.</p>\n'}, {'answer_id': 37907735, 'author': 'Shonn Lyga', 'author_id': 1951795, 'author_profile': 'https://Stackoverflow.com/users/1951795', 'pm_score': 0, 'selected': False, 'text': '<p>Much more contemporary and Task based code would look something like this:</p>\n\n<pre class="lang-cs prettyprint-override"><code>public string ReadLine(int timeOutMillisecs)\n{\n    var inputBuilder = new StringBuilder();\n\n    var task = Task.Factory.StartNew(() =&gt;\n    {\n        while (true)\n        {\n            var consoleKey = Console.ReadKey(true);\n            if (consoleKey.Key == ConsoleKey.Enter)\n            {\n                return inputBuilder.ToString();\n            }\n\n            inputBuilder.Append(consoleKey.KeyChar);\n        }\n    });\n\n\n    var success = task.Wait(timeOutMillisecs);\n    if (!success)\n    {\n        throw new TimeoutException("User did not provide input within the timelimit.");\n    }\n\n    return inputBuilder.ToString();\n}\n</code></pre>\n'}, {'answer_id': 39154725, 'author': 'JJS', 'author_id': 26877, 'author_profile': 'https://Stackoverflow.com/users/26877', 'pm_score': 0, 'selected': False, 'text': '<p>I had a unique situation of having a Windows Application (Windows Service). When running the program interactively <code>Environment.IsInteractive</code> (VS Debugger or from cmd.exe), I used AttachConsole/AllocConsole to get my stdin/stdout. \nTo keep the process from ending while the work was being done, the UI Thread calls <code>Console.ReadKey(false)</code>. 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.</p>\n\n<pre><code>using System;\nusing System.Diagnostics;\n\ninternal class PressAnyKey\n{\n  private static Thread inputThread;\n  private static AutoResetEvent getInput;\n  private static AutoResetEvent gotInput;\n  private static CancellationTokenSource cancellationtoken;\n\n  static PressAnyKey()\n  {\n    // Static Constructor called when WaitOne is called (technically Cancel too, but who cares)\n    getInput = new AutoResetEvent(false);\n    gotInput = new AutoResetEvent(false);\n    inputThread = new Thread(ReaderThread);\n    inputThread.IsBackground = true;\n    inputThread.Name = "PressAnyKey";\n    inputThread.Start();\n  }\n\n  private static void ReaderThread()\n  {\n    while (true)\n    {\n      // ReaderThread waits until PressAnyKey is called\n      getInput.WaitOne();\n      // Get here \n      // Inner loop used when a caller uses PressAnyKey\n      while (!Console.KeyAvailable &amp;&amp; !cancellationtoken.IsCancellationRequested)\n      {\n        Thread.Sleep(50);\n      }\n      // Release the thread that called PressAnyKey\n      gotInput.Set();\n    }\n  }\n\n  /// &lt;summary&gt;\n  /// Signals the thread that called WaitOne should be allowed to continue\n  /// &lt;/summary&gt;\n  public static void Cancel()\n  {\n    // Trigger the alternate ending condition to the inner loop in ReaderThread\n    if(cancellationtoken== null) throw new InvalidOperationException("Must call WaitOne before Cancelling");\n    cancellationtoken.Cancel();\n  }\n\n  /// &lt;summary&gt;\n  /// Wait until a key is pressed or &lt;see cref="Cancel"/&gt; is called by another thread\n  /// &lt;/summary&gt;\n  public static void WaitOne()\n  {\n    if(cancellationtoken==null || cancellationtoken.IsCancellationRequested) throw new InvalidOperationException("Must cancel a pending wait");\n    cancellationtoken = new CancellationTokenSource();\n    // Release the reader thread\n    getInput.Set();\n    // Calling thread will wait here indefiniately \n    // until a key is pressed, or Cancel is called\n    gotInput.WaitOne();\n  }    \n}\n</code></pre>\n'}, {'answer_id': 42940552, 'author': 'Igorium', 'author_id': 6268624, 'author_profile': 'https://Stackoverflow.com/users/6268624', 'pm_score': 1, 'selected': False, 'text': '<p>Here is safe solution which fakes console input to unblock thread after timeout.\n<a href="https://github.com/Igorium/ConsoleReader" rel="nofollow noreferrer">https://github.com/Igorium/ConsoleReader</a> project provides a sample user dialog implementation.</p>\n\n<pre><code>var inputLine = ReadLine(5);\n\npublic static string ReadLine(uint timeoutSeconds, Func&lt;uint, string&gt; countDownMessage, uint samplingFrequencyMilliseconds)\n{\n    if (timeoutSeconds == 0)\n        return null;\n\n    var timeoutMilliseconds = timeoutSeconds * 1000;\n\n    if (samplingFrequencyMilliseconds &gt; timeoutMilliseconds)\n        throw new ArgumentException("Sampling frequency must not be greater then timeout!", "samplingFrequencyMilliseconds");\n\n    CancellationTokenSource cts = new CancellationTokenSource();\n\n    Task.Factory\n        .StartNew(() =&gt; SpinUserDialog(timeoutMilliseconds, countDownMessage, samplingFrequencyMilliseconds, cts.Token), cts.Token)\n        .ContinueWith(t =&gt; {\n            var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;\n            PostMessage(hWnd, 0x100, 0x0D, 9);\n        }, TaskContinuationOptions.NotOnCanceled);\n\n\n    var inputLine = Console.ReadLine();\n    cts.Cancel();\n\n    return inputLine;\n}\n\n\nprivate static void SpinUserDialog(uint countDownMilliseconds, Func&lt;uint, string&gt; countDownMessage, uint samplingFrequencyMilliseconds,\n    CancellationToken token)\n{\n    while (countDownMilliseconds &gt; 0)\n    {\n        token.ThrowIfCancellationRequested();\n\n        Thread.Sleep((int)samplingFrequencyMilliseconds);\n\n        countDownMilliseconds -= countDownMilliseconds &gt; samplingFrequencyMilliseconds\n            ? samplingFrequencyMilliseconds\n            : countDownMilliseconds;\n    }\n}\n\n\n[DllImport("User32.Dll", EntryPoint = "PostMessageA")]\nprivate static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);\n</code></pre>\n'}, {'answer_id': 43651242, 'author': 'georgiosd', 'author_id': 165656, 'author_profile': 'https://Stackoverflow.com/users/165656', 'pm_score': 0, 'selected': False, 'text': '<p>This seems to be the simplest, working solution, that doesn\'t use any native APIs:</p>\n\n<pre><code>    static Task&lt;string&gt; ReadLineAsync(CancellationToken cancellation)\n    {\n        return Task.Run(() =&gt;\n        {\n            while (!Console.KeyAvailable)\n            {\n                if (cancellation.IsCancellationRequested)\n                    return null;\n\n                Thread.Sleep(100);\n            }\n            return Console.ReadLine();\n        });\n    }\n</code></pre>\n\n<p>Example usage:</p>\n\n<pre><code>    static void Main(string[] args)\n    {\n        AsyncContext.Run(async () =&gt;\n        {\n            CancellationTokenSource cancelSource = new CancellationTokenSource();\n            cancelSource.CancelAfter(1000);\n            Console.WriteLine(await ReadLineAsync(cancelSource.Token) ?? "null");\n        });\n    }\n</code></pre>\n'}, {'answer_id': 44760134, 'author': 'kwl', 'author_id': 2846791, 'author_profile': 'https://Stackoverflow.com/users/2846791', 'pm_score': 3, 'selected': False, 'text': "<p>If you're in the <code>Main()</code> method, you can't use <code>await</code>, so you'll have to use <code>Task.WaitAny()</code>:</p>\n\n<pre><code>var task = Task.Factory.StartNew(Console.ReadLine);\nvar result = Task.WaitAny(new Task[] { task }, TimeSpan.FromSeconds(5)) == 0\n    ? task.Result : string.Empty;\n</code></pre>\n\n<p>However, C# 7.1 introduces the possiblity to create an async <code>Main()</code> method, so it's better to use the <code>Task.WhenAny()</code> version whenever you have that option:</p>\n\n<pre><code>var task = Task.Factory.StartNew(Console.ReadLine);\nvar completedTask = await Task.WhenAny(task, Task.Delay(TimeSpan.FromSeconds(5)));\nvar result = object.ReferenceEquals(task, completedTask) ? task.Result : string.Empty;\n</code></pre>\n"}, {'answer_id': 46226327, 'author': 'Nicholas Petersen', 'author_id': 264031, 'author_profile': 'https://Stackoverflow.com/users/264031', 'pm_score': 2, 'selected': False, 'text': '<p>As if there weren\'t already enough answers here :0), the following encapsulates into a static method @kwl\'s solution above (the first one). </p>\n\n<pre><code>    public static string ConsoleReadLineWithTimeout(TimeSpan timeout)\n    {\n        Task&lt;string&gt; task = Task.Factory.StartNew(Console.ReadLine);\n\n        string result = Task.WaitAny(new Task[] { task }, timeout) == 0\n            ? task.Result \n            : string.Empty;\n        return result;\n    }\n</code></pre>\n\n<p>Usage</p>\n\n<pre><code>    static void Main()\n    {\n        Console.WriteLine("howdy");\n        string result = ConsoleReadLineWithTimeout(TimeSpan.FromSeconds(8.5));\n        Console.WriteLine("bye");\n    }\n</code></pre>\n'}, {'answer_id': 55320462, 'author': 'Sergio Cabral', 'author_id': 1396511, 'author_profile': 'https://Stackoverflow.com/users/1396511', 'pm_score': 2, 'selected': False, 'text': '<p><em>My code is based entirely on the friend\'s answer @JSQuareD</em></p>\n\n<p>But I needed to use <code>Stopwatch</code> to timer because when I finished the program with <code>Console.ReadKey()</code> it was still waiting for <code>Console.ReadLine()</code> and it generated unexpected behavior.</p>\n\n<p><strong>It WORKED PERFECTLY for me. Maintains the original Console.ReadLine ()</strong></p>\n\n<pre><code>class Program\n{\n    static void Main(string[] args)\n    {\n        Console.WriteLine("What is the answer? (5 secs.)");\n        try\n        {\n            var answer = ConsoleReadLine.ReadLine(5000);\n            Console.WriteLine("Answer is: {0}", answer);\n        }\n        catch\n        {\n            Console.WriteLine("No answer");\n        }\n        Console.ReadKey();\n    }\n}\n\nclass ConsoleReadLine\n{\n    private static string inputLast;\n    private static Thread inputThread = new Thread(inputThreadAction) { IsBackground = true };\n    private static AutoResetEvent inputGet = new AutoResetEvent(false);\n    private static AutoResetEvent inputGot = new AutoResetEvent(false);\n\n    static ConsoleReadLine()\n    {\n        inputThread.Start();\n    }\n\n    private static void inputThreadAction()\n    {\n        while (true)\n        {\n            inputGet.WaitOne();\n            inputLast = Console.ReadLine();\n            inputGot.Set();\n        }\n    }\n\n    // omit the parameter to read a line without a timeout\n    public static string ReadLine(int timeout = Timeout.Infinite)\n    {\n        if (timeout == Timeout.Infinite)\n        {\n            return Console.ReadLine();\n        }\n        else\n        {\n            var stopwatch = new Stopwatch();\n            stopwatch.Start();\n\n            while (stopwatch.ElapsedMilliseconds &lt; timeout &amp;&amp; !Console.KeyAvailable) ;\n\n            if (Console.KeyAvailable)\n            {\n                inputGet.Set();\n                inputGot.WaitOne();\n                return inputLast;\n            }\n            else\n            {\n                throw new TimeoutException("User did not provide input within the timelimit.");\n            }\n        }\n    }\n}\n</code></pre>\n'}, {'answer_id': 66821954, 'author': 'scott', 'author_id': 1769757, 'author_profile': 'https://Stackoverflow.com/users/1769757', 'pm_score': 1, 'selected': False, 'text': '<p>I\'ve got a solution to this using the Windows API that has some benefits over many of the solutions here:</p>\n<ul>\n<li>Uses Console.ReadLine to retrieve the input, so you get all of the niceties associated with that (input history, etc)</li>\n<li>Forces the Console.ReadLine call to complete after the timeout, so you don\'t accumulate a new thread for every call that times out.</li>\n<li>Doesn\'t abort a thread unsafely.</li>\n<li>Doesn\'t have issues with focus like the input faking approach does.</li>\n</ul>\n<p>The two main downsides:</p>\n<ul>\n<li>Only works on Windows.</li>\n<li>It\'s pretty complicated.</li>\n</ul>\n<p>The basic idea is that the Windows API has a function to cancel outstanding I/O requests: <a href="https://learn.microsoft.com/en-us/windows/win32/fileio/cancelioex-func" rel="nofollow noreferrer">CancelIoEx</a>. When you use it to cancel operations on STDIN, Console.ReadLine throws an OperationCanceledException.</p>\n<p>So here\'s how you do it:</p>\n<pre class="lang-cs prettyprint-override"><code>using System;\nusing System.Runtime.InteropServices;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace ConsoleHelper\n{\n    public static class ConsoleHelper\n    {\n        public static string ReadLine(TimeSpan timeout)\n        {\n            return ReadLine(Task.Delay(timeout));\n        }\n\n        public static string ReadLine(Task cancel_trigger)\n        {\n            var status = new Status();\n\n            var cancel_task = Task.Run(async () =&gt;\n            {\n                await cancel_trigger;\n\n                status.Mutex.WaitOne();\n                bool io_done = status.IODone;\n                if (!io_done)\n                    status.CancellationStarted = true;\n                status.Mutex.ReleaseMutex();\n\n                while (!status.IODone)\n                {\n                    var success = CancelStdIn(out int error_code);\n\n                    if (!success &amp;&amp; error_code != 0x490) // 0x490 is what happens when you call cancel and there is not a pending I/O request\n                        throw new Exception($&quot;Canceling IO operation on StdIn failed with error {error_code} ({error_code:x})&quot;);\n                }\n            });\n\n            ReadLineWithStatus(out string input, out bool read_canceled);\n            \n            if (!read_canceled)\n            {\n                status.Mutex.WaitOne();\n                bool must_wait = status.CancellationStarted;\n                status.IODone = true;\n                status.Mutex.ReleaseMutex();\n\n                if (must_wait)\n                    cancel_task.Wait();\n\n                return input;\n            }\n            else // read_canceled == true\n            {\n                status.Mutex.WaitOne();\n                bool cancel_started = status.CancellationStarted;\n                status.IODone = true;\n                status.Mutex.ReleaseMutex();\n\n                if (!cancel_started)\n                    throw new Exception(&quot;Received cancelation not triggered by this method.&quot;);\n                else\n                    cancel_task.Wait();\n\n                return null;\n            }\n        }\n\n        private const int STD_INPUT_HANDLE = -10;\n\n        [DllImport(&quot;kernel32.dll&quot;, SetLastError = true)]\n        private static extern IntPtr GetStdHandle(int nStdHandle);\n\n        [DllImport(&quot;kernel32.dll&quot;, SetLastError = true)]\n        private static extern bool CancelIoEx(IntPtr handle, IntPtr lpOverlapped);\n\n\n        private static bool CancelStdIn(out int error_code)\n        {\n            var handle = GetStdHandle(STD_INPUT_HANDLE);\n            bool success = CancelIoEx(handle, IntPtr.Zero);\n\n            if (success)\n            {\n                error_code = 0;\n                return true;\n            }\n            else\n            {\n                var rc = Marshal.GetLastWin32Error();\n                error_code = rc;\n                return false;\n            }\n        }\n\n        private class Status\n        {\n            public Mutex Mutex = new Mutex(false);\n            public volatile bool IODone;\n            public volatile bool CancellationStarted;\n        }\n\n        private static void ReadLineWithStatus(out string result, out bool operation_canceled)\n        {\n            try\n            {\n                result = Console.ReadLine();\n                operation_canceled = false;\n            }\n            catch (OperationCanceledException)\n            {\n                result = null;\n                operation_canceled = true;\n            }\n        }\n    }\n}\n\n</code></pre>\n<p>Avoid the temptation to simplify this, getting the threading right is pretty tricky. You need to handle all of these cases:</p>\n<ul>\n<li>Cancel is triggered and <code>CancelStdIn</code> is called before <code>Console.ReadLine</code> starts (this is why you need the loop in the <code>cancel_trigger</code>).</li>\n<li>Console.ReadLine returns before cancel is triggered (possibly long before).</li>\n<li>Console.ReadLine returns after the cancel is triggered but before <code>CancelStdIn</code> is called.</li>\n<li>Console.ReadLine throws an exception due to the call to <code>CancelStdIn</code> in response to the cancel trigger.</li>\n</ul>\n<p>Credits:\nGot the idea for CancelIoEx from a <a href="https://stackoverflow.com/a/58475263/1769757">SO answer</a> who got it from <a href="https://www.meziantou.net/cancelling-console-read.htm" rel="nofollow noreferrer">Gérald Barré\'s blog</a>. However those solutions have subtle concurrency bugs.</p>\n'}]
['https://Stackoverflow.com/questions/57615', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/337/']