我有一个控制台应用程序,我想给用户x秒的时间来响应提示.如果在一段时间后没有输入,程序逻辑应该继续.我们假设超时意味着空响应.
解决这一问题最直接的方法是什么?
我有一个控制台应用程序,我想给用户x秒的时间来响应提示.如果在一段时间后没有输入,程序逻辑应该继续.我们假设超时意味着空响应.
解决这一问题最直接的方法是什么?
我惊讶地发现,5年后,所有的答案仍然存在以下一个或多个问题:
我相信我的解决方案将解决最初的问题,而不会出现上述任何问题:
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)
公约,正如shmueli所建议的:
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
并省略超时,这样它就默认为无限超时.
那么我提到的其他解决方案的问题呢?
我预见到这个解决方案的唯一问题是它不是线程安全的.然而,多个线程不能同时请求用户输入,所以在调用Reader.ReadLine
之前应该先进行同步.