令我惊讶的是,五年后,所有答案仍然遭受以下一个或多个问题的困扰:
我相信我的解决方案将解决原来的问题,而不会遇到上述任何问题:
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
无论如何都要在调用之前进行同步。