如何向Console.ReadLine()添加超时?我有一个控制台应用程序,我想在其中给用户x秒来响应提示符。如果在一段时间后没有输入,则程序逻辑应该继续。我们假设超时意味着空响应。最直截了当的方法是什么?
3 回答
MM们
TA贡献1886条经验 获得超2个赞
使用的是ReadLine以外的函数,导致功能丢失。(删除/退格/向上键用于先前的输入)。 函数在多次调用(产生多个线程、许多挂起的ReadLine或其他意外行为)时表现不好。 函数依赖于繁忙的等待。这是一种可怕的浪费,因为等待被期望在任何地方运行,从几秒钟到超时,这可能是多分钟。一个繁忙的等待,跑了这么长的时间,是一个可怕的吸资源,这是特别糟糕的多线程场景。如果用睡眠来修改繁忙-等待,这会对响应性产生负面影响,尽管我承认这可能不是什么大问题。
class Reader { private static Thread inputThread; private static AutoResetEvent getInput, gotInput; private static string input; static Reader() { getInput = new AutoResetEvent(false); gotInput = new AutoResetEvent(false); inputThread = new Thread(reader); inputThread.IsBackground = true; inputThread.Start(); } private static void reader() { while (true) { getInput.WaitOne(); input = Console.ReadLine(); gotInput.Set(); } } // omit the parameter to read a line without a timeout public static string ReadLine(int timeOutMillisecs = Timeout.Infinite) { getInput.Set(); bool success = gotInput.WaitOne(timeOutMillisecs); if (success) return input; else throw new TimeoutException("User did not provide input within the timelimit."); }}
try { Console.WriteLine("Please enter your name within the next 5 seconds."); string name = Reader.ReadLine(5000); Console.WriteLine("Hello, {0}!", name);} catch (TimeoutException) { Console.WriteLine("Sorry, you waited too long.");}
TryXX(out)
public static bool TryReadLine(out string line, int timeOutMillisecs = Timeout.Infinite) { getInput.Set(); bool success = gotInput.WaitOne(timeOutMillisecs); if (success) line = input; else line = null; return success; }
Console.WriteLine("Please enter your name within the next 5 seconds.");string name;bool success = Reader.TryReadLine(out name, 5000);if (!success) Console.WriteLine("Sorry, you waited too long.");else Console.WriteLine("Hello, {0}!", name);
Reader
Console.ReadLine
Reader
ReadLine
ReadLine
Reader
如您所见,使用ReadLine,避免了第一个问题。 该函数在多次调用时运行正常。不管是否发生超时,只有一个后台线程将运行,并且最多只有一个对ReadLine的调用将是活动的。调用函数总是会导致最新的输入,或者超时,用户不必多次按Enter键才能提交输入。 而且,很明显,这个函数不依赖于繁忙的等待。相反,它使用适当的多线程技术来防止资源浪费。
Reader.ReadLine
达令说
TA贡献1821条经验 获得超6个赞
string ReadLine(int timeoutms){ ReadLineDelegate d = Console.ReadLine; IAsyncResult result = d.BeginInvoke(null, null); result.AsyncWaitHandle.WaitOne(timeoutms);//timeout e.g. 15000 for 15 secs if (result.IsCompleted) { string resultstr = d.EndInvoke(result); Console.WriteLine("Read: " + resultstr); return resultstr; } else { Console.WriteLine("Timed out!"); throw new TimedoutException("Timed Out!"); }}delegate string ReadLineDelegate();
开心每一天1111
TA贡献1836条经验 获得超13个赞
class Sample { public static void Main() { ConsoleKeyInfo cki = new ConsoleKeyInfo(); do { Console.WriteLine("\nPress a key to display; press the 'x' key to quit.");// Your code could perform some useful task in the following loop. However, // for the sake of this example we'll merely pause for a quarter second. while (Console.KeyAvailable == false) Thread.Sleep(250); // Loop until input is entered. cki = Console.ReadKey(true); Console.WriteLine("You pressed the '{0}' key.", cki.Key); } while(cki.Key != ConsoleKey.X); }}
- 3 回答
- 0 关注
- 1293 浏览
添加回答
举报
0/150
提交
取消