MM们
我惊讶地获悉,五年后,所有答案仍然存在以下一个或多个问题:使用的是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)如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并省略超时,使其默认为无限超时。那么我提到的其他解决方案的问题呢?如您所见,使用ReadLine,避免了第一个问题。该函数在多次调用时运行正常。不管是否发生超时,只有一个后台线程将运行,并且最多只有一个对ReadLine的调用将是活动的。调用函数总是会导致最新的输入,或者超时,用户不必多次按Enter键才能提交输入。而且,很明显,这个函数不依赖于繁忙的等待。相反,它使用适当的多线程技术来防止资源浪费。我认为这个解决方案唯一的问题是它不是线程安全的。但是,多个线程实际上不能同时请求用户输入,因此在调用Reader.ReadLine不管怎么说。