Skip to content

Instantly share code, notes, and snippets.

@Sidneys1
Created October 27, 2016 12:33
Show Gist options
  • Save Sidneys1/b1c6efb7d5d10843c32b9dcf63753a13 to your computer and use it in GitHub Desktop.
Save Sidneys1/b1c6efb7d5d10843c32b9dcf63753a13 to your computer and use it in GitHub Desktop.
A ReadLine wrapper that allows cancellable and timeoutable Console.ReadLine calls
internal static class InterruptableReadline {
private static readonly AutoResetEvent StartReading = new AutoResetEvent(false);
private static readonly AutoResetEvent DoneReading = new AutoResetEvent(false);
private static readonly Thread ReadThread = new Thread(ReadThreadMain) { IsBackground = true };
private static string _readVal;
private static bool _cancelled;
static InterruptableReadline() { ReadThread.Start(); }
public static void Shutdown() { ReadThread.Abort(); }
private static void ReadThreadMain() {
while (true) {
StartReading.WaitOne();
_readVal = Console.ReadLine();
DoneReading.Set();
}
}
public static string ReadLine() => ReadLine(new TimeSpan(0, 0, 0, 0, -1));
public static string ReadLine(int milliseconds) => ReadLine(new TimeSpan(0, 0, 0, 0, milliseconds));
public static string ReadLine(TimeSpan timeout) {
lock (StartReading) { // Prevent concurrent calls
_readVal = null;
_cancelled = false;
StartReading.Set();
if (!DoneReading.WaitOne(timeout))
throw new TimeoutException("The ReadLine timeout expired.");
if (_readVal == null && _cancelled)
throw new OperationCanceledException("The ReadLine was cancelled.");
return _readVal;
}
}
public static void CancelReadline() {
_cancelled = true;
DoneReading.Set();
lock (StartReading) { } // Make sure the ReadLine method returns first
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment