我需要在控制台中请求输入,并等待几秒钟,然后默认设置为某个值。如何在C#中基本计时控制台输入,并使用默认设置?如果您有示例代码,那就太好了。
我需要在控制台中请求输入,并等待几秒钟,然后默认设置为某个值。如何在C#中基本计时控制台输入,并使用默认设置?如果您有示例代码,那就太好了。
static void Main(string[] args)
{
System.Timers.Timer timer = new System.Timers.Timer(60000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(T_Elapsed);
timer.Start();
var i = Console.ReadLine();
if (string.IsNullOrEmpty(i))
{
timer.Stop();
Console.WriteLine("{0}", i);
}
}
static void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Console.WriteLine("Defult Values Used");
var T = (Timer)sender;
T.Stop;
}
不确定这是否是最好的方法。我已经测试过了,但正如我所说,这可能不是最好的方式。
您可能希望考虑添加一个命令行参数,以充当自动模式和完全用户输入模式之间的开关。
如果您使用特定的解释方式,则变得非常简单。在此模型中,提示用户进行输入。如果超时时间内未输入任何内容,则使用默认值。如果他们开始输入,则不使用超时时间。这也解决了可用性问题,即当他们花费很长时间输入内容时,放弃并使用默认值。
static void Main(string[] args)
{
Console.WriteLine("Please enter your name ");
string input;
if (TryReadLine(out input, 10000, true))
{
Console.WriteLine(input);
}
else
{
Console.WriteLine("[DEFAULT]");
}
Console.ReadKey(true);
}
const string timerString = "[{0} seconds until default value is used]";
public static bool TryReadLine(out string s, double timeout, bool showTimer)
{
DateTime timeoutDateTime = DateTime.Now.AddMilliseconds(10000);
DateTime nextTimer = DateTime.Now;
while (DateTime.Now < timeoutDateTime)
{
if (Console.KeyAvailable)
{
ClearTimer(timeoutDateTime);
s = Console.ReadLine();
return true;
}
if (showTimer && DateTime.Now > nextTimer)
{
WriteTimer(string.Format(timerString, (timeoutDateTime - DateTime.Now).Seconds));
nextTimer = DateTime.Now.AddSeconds(1);
}
}
ClearTimer(timeoutDateTime);
s = null;
return false;
}
private static void ClearTimer(DateTime timeoutDateTime)
{
WriteTimer(new string(' ', string.Format(timerString, (timeoutDateTime - DateTime.Now).Seconds).Length));
}
private static void WriteTimer(string s)
{
int cursorLeft = Console.CursorLeft;
Console.CursorLeft = 0;
Console.CursorTop += 1;
Console.Write(s);
Console.CursorLeft = cursorLeft;
Console.CursorTop -= 1;
}
}
因为在我意识到有更好的方法之前,我花了很长时间,所以这里是一些我刚刚编写的代码,用于从控制台读取字符串,并具有超时选项。它还可以选择将剩余时间打印到控制台。它没有经过非常彻底的测试,因此可能存在许多错误。回调功能使用.NET 3.0 Action,但如果这是针对C# 2.0,则可以将其转换为委托。
static void Main(string[] args)
{
string input;
Console.Write("Please enter your name (");
int timerPromptStart = Console.CursorLeft;
Console.Write(" seconds left): ");
if (TryReadLine(out input, 10000, delegate(TimeSpan timeSpan)
{
int inputPos = Console.CursorLeft;
Console.CursorLeft = timerPromptStart;
Console.Write(timeSpan.Seconds.ToString("000"));
Console.CursorLeft = inputPos;
},
1000))
{
Console.WriteLine(input);
}
else
{
Console.WriteLine("DEFAULT");
}
while (true) { }
}
/// <summary>
/// Tries to read a line of input from the Console.
/// </summary>
/// <param name="s">The string to put the input into.</param>
/// <param name="timeout">The time in milliseconds before the attempt fails.</param>
/// <returns>Whether the user inputted a line before the timeout.</returns>
public static bool TryReadLine(out string s, double timeout)
{
return TryReadLine(out s, timeout, null, 0);
}
/// <summary>
/// Tries to read a line of input from the Console.
/// </summary>
/// <param name="s">The string to put the input into.</param>
/// <param name="timeout">The time in milliseconds before the attempt fails.</param>
/// <param name="timerCallback">A function to call every callbackInterval.</param>
/// <param name="callbackInterval">The length of time between calls to timerCallback.</param>
/// <returns>Whether the user inputted a line before the timeout.</returns>
public static bool TryReadLine(out string s, double timeout, Action<TimeSpan> timerCallback, double callbackInterval)
{
const int tabLength = 6;
StringBuilder inputBuilder = new StringBuilder();
int readStart = Console.CursorLeft;
int lastLength = 0;
bool isInserting = true;
DateTime endTime = DateTime.Now.AddMilliseconds(timeout);
DateTime nextCallback = DateTime.Now;
while (DateTime.Now < endTime)
{
if (timerCallback != null && DateTime.Now > nextCallback)
{
nextCallback = DateTime.Now.AddMilliseconds(callbackInterval);
timerCallback((endTime - DateTime.Now));
}
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey(true);
switch (key.Key)
{
case ConsoleKey.Enter:
Console.WriteLine();
s = inputBuilder.ToString();
return true;
case ConsoleKey.Backspace:
if (Console.CursorLeft > readStart)
{
Console.CursorLeft -= 1;
inputBuilder.Remove(Console.CursorLeft - readStart, 1);
}
break;
case ConsoleKey.Delete:
if (Console.CursorLeft < readStart + inputBuilder.Length)
{
inputBuilder.Remove(Console.CursorLeft - readStart, 1);
}
break;
case ConsoleKey.Tab:
// Tabs are very difficult to handle properly, so we'll simply replace it with spaces.
AddOrInsert(inputBuilder, new String(' ', tabLength), isInserting, readStart);
Console.CursorLeft += tabLength;
break;
case ConsoleKey.Escape:
Console.CursorLeft = readStart;
inputBuilder = new StringBuilder();
break;
case ConsoleKey.Insert:
isInserting = !isInserting;
// This may be dependant on a variable somewhere.
if (isInserting)
{
Console.CursorSize = 25;
}
else
{
Console.CursorSize = 50;
}
break;
case ConsoleKey.Home:
Console.CursorLeft = readStart;
break;
case ConsoleKey.End:
Console.CursorLeft = readStart + inputBuilder.Length;
break;
case ConsoleKey.LeftArrow:
if (Console.CursorLeft > readStart)
{
Console.CursorLeft -= 1;
}
break;
case ConsoleKey.RightArrow:
if (Console.CursorLeft < readStart + inputBuilder.Length)
{
Console.CursorLeft += 1;
}
break;
case ConsoleKey.UpArrow:
// N.B. We can't handle Up like we normally would as we don't know the last console input.
// You might want to handle this so it works appropriately within your own application.
break;
case ConsoleKey.PageUp:
case ConsoleKey.PageDown:
case ConsoleKey.PrintScreen:
case ConsoleKey.LeftWindows:
case ConsoleKey.RightWindows:
case ConsoleKey.Sleep:
case ConsoleKey.F1:
case ConsoleKey.F2:
case ConsoleKey.F3:
case ConsoleKey.F4:
case ConsoleKey.F5:
case ConsoleKey.F6:
case ConsoleKey.F7:
case ConsoleKey.F8:
case ConsoleKey.F9:
case ConsoleKey.F10:
case ConsoleKey.F11:
case ConsoleKey.F12:
case ConsoleKey.F13:
case ConsoleKey.F14:
case ConsoleKey.F15:
case ConsoleKey.F16:
case ConsoleKey.F17:
case ConsoleKey.F18:
case ConsoleKey.F19:
case ConsoleKey.F20:
case ConsoleKey.F21:
case ConsoleKey.F22:
case ConsoleKey.F23:
case ConsoleKey.F24:
case ConsoleKey.BrowserBack:
case ConsoleKey.BrowserForward:
case ConsoleKey.BrowserStop:
case ConsoleKey.BrowserRefresh:
case ConsoleKey.BrowserSearch:
case ConsoleKey.BrowserFavorites:
case ConsoleKey.BrowserHome:
case ConsoleKey.VolumeMute:
case ConsoleKey.VolumeUp:
case ConsoleKey.VolumeDown:
case ConsoleKey.MediaNext:
case ConsoleKey.MediaPrevious:
case ConsoleKey.MediaStop:
case ConsoleKey.MediaPlay:
case ConsoleKey.LaunchMail:
case ConsoleKey.LaunchMediaSelect:
case ConsoleKey.LaunchApp1:
case ConsoleKey.LaunchApp2:
case ConsoleKey.Play:
case ConsoleKey.Zoom:
case ConsoleKey.NoName:
case ConsoleKey.Pa1:
// These keys shouldn't do anything.
break;
case ConsoleKey.Clear:
case ConsoleKey.Pause:
case ConsoleKey.Select:
case ConsoleKey.Print:
case ConsoleKey.Execute:
case ConsoleKey.Process:
case ConsoleKey.Help:
case ConsoleKey.Applications:
case ConsoleKey.Packet:
case ConsoleKey.Attention:
case ConsoleKey.CrSel:
case ConsoleKey.ExSel:
case ConsoleKey.EraseEndOfFile:
case ConsoleKey.OemClear:
// I'm not sure what these do.
break;
default:
Console.Write(key.KeyChar);
AddOrInsert(inputBuilder, key.KeyChar.ToString(), isInserting, readStart);
break;
}
// Write what has current been typed in back out to the Console.
// We write out everything after the cursor to handle cases where the current input string is shorter than before
// (i.e. the user deleted stuff).
// There is probably a more efficient way to do this.
int oldCursorPos = Console.CursorLeft;
Console.CursorLeft = readStart;
Console.Write(inputBuilder.ToString());
if (lastLength > inputBuilder.Length)
{
Console.Write(new String(' ', lastLength - inputBuilder.Length));
}
lastLength = inputBuilder.Length;
Console.CursorLeft = oldCursorPos;
}
}
// The timeout period was reached.
Console.WriteLine();
s = null;
return false;
}
// This is a rather ugly helper method to add text to the inputBuilder, either inserting or appending as appropriate.
private static void AddOrInsert(StringBuilder inputBuilder, string s, bool insert, int readStart)
{
if (Console.CursorLeft < readStart + inputBuilder.Length + (insert ? -1 : 1))
{
if (!insert)
{
inputBuilder.Remove(Console.CursorLeft - 1 - readStart, 1);
}
inputBuilder.Insert(Console.CursorLeft - 1 - readStart, s);
}
else
{
inputBuilder.Append(s);
}
}
}