如何向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);ReaderConsole.ReadLineReaderReadLineReadLineReader
如您所见,使用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 关注
- 1381 浏览
添加回答
举报
0/150
提交
取消
