如何在 C# 中等待控制台输入 15 秒左右

发布于 2024-07-08 00:03:18 字数 93 浏览 8 评论 0原文

我需要在控制台中请求输入,然后等待几秒钟,可能一分钟后我需要默认为某个值。 如何基本上对 C# 中的控制台输入进行计时并继续使用默认设置? 如果您有示例代码那就太好了。

I need to ask for input in console and wait for few sec may be a min after that I need to default to some value. How can basically time our on console input in c# and proceed with default settings? If you have sample code that would be great.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

请恋爱 2024-07-15 00:03:18

您可以使用 System.Timers.Timer 中的计时器对象并将其设置为 60 秒,启用它,如果有人在控制台中输入某些内容,则将其禁用,如果没有,则只需处理 Timer.Elapsed 事件中发生的情况。

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;

        }

不确定这是否是最好的方法。 我已经对此进行了测试,但正如我所说,这可能不是最好的方法。

You could use the timer object in System.Timers.Timer and set it to 60 secs, enable it and if someone enters something into the console just disable it, if not then just handle the what happens in the Timer.Elapsed event.

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;

        }

Not sure if this is the best way. I have tested this but as I said it may not be the best way.

情丝乱 2024-07-15 00:03:18

您可能需要考虑执行一些操作,例如添加命令行参数以充当使用默认值的自动模式和完整用户输入模式之间的切换。

如果您对您的请求使用特定的解释,那么它就会变得非常微不足道。 在此模型中,系统会提示用户输入。 如果他们在超时后没有输入任何内容,则使用默认值。 如果他们开始输入内容,则不会使用超时。 这也解决了当他们花费很长时间输入内容时放弃并使用默认值的可用性问题。

    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);
        }
    }
}

You may want to consider doing something like adding a command line argument to act as a switch between an automatic mode using defaults and the full user input mode.

If you use a specific interpretation of your request it becomes quite trivial. In this model the user is prompted for input. If they type nothing after a timeout period the default value is used. If they start typing something then no timeout is used. This also deals with the usability issue of giving up and using a default value when they're taking a long time to type something in.

    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;
    }
}

Because I spend so long on it before I realised there was a better way, here is some code I just knocked up to read a string from the console, with a timeout. It also has the option to be able to print the current time left to the console. It's not tested very thoroughly, so is likely to have a lot of bugs. The callback feature uses the .NET 3.0 Action, though if this is for C# 2.0 you can just turn it into a delegate.

    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);
        }
    }
}
七分※倦醒 2024-07-15 00:03:18

请参阅此处,它在控制台上使用了一种很好的小轮询技术,虽然有点粗糙,但非常有效。

See here, it uses a nice little polling technique on the console, which although a bit crude, very effective.

平定天下 2024-07-15 00:03:18

一种方法是循环,调用 Console.In.Peek(),等待输入或等待足够的时间。

One way would be to loop, calling Console.In.Peek(), waiting for input or for enough time to go by.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文