C# |控制台应用程序 |如何在执行下一行之前让程序等待(以毫秒为单位的时间)?

Posted

技术标签:

【中文标题】C# |控制台应用程序 |如何在执行下一行之前让程序等待(以毫秒为单位的时间)?【英文标题】:C# | Console app | How to make the program wait (time in ms) before executing the next line? 【发布时间】:2019-09-03 13:10:09 【问题描述】:

我正在构建一个 c# 控制台应用程序(.NET 框架),我想通过使用一些“动画”来制作一个漂亮的应用程序。 我想打印“Press any Key to continue ...”并让它闪烁(出现然后消失,直到用户实际按下任何键。

 do
    
       while (!Console.KeyAvailable)
         
             Console.WriteLine("Press any key to continue...");

     /* here i want the program to wait for like 500ms,
      clear console and wait 500ms again before rewriting line*/

             Console.Clear();
         
      while (Console.ReadKey(true).Key != ConsoleKey.Escape);

【问题讨论】:

Thread.Sleep(500) ? 【参考方案1】:

一个简单的方法是使用

System.Threading.Thread.Sleep(5000); //暂停5秒。所以要闪存做这个。

Console.Clear();
Console.WriteLine("SomeText");
System.Threading.Thread.Sleep(1000);
Console.Clear();
Console.WriteLine("SomeText");
System.Threading.Thread.Sleep(1000);
/// ETC.. 

Console.WriteLine("Press Any key To Continue...)

这是一种简单的方法,有助于您理解编码。如果你想让它继续闪烁,那么只需将它放在一个循环内。然而!请记住,这有效地“暂停”了代码运行。因此,如果它在暂停线上,它将不允许用户按下键继续。这就是为什么我把最后的Console.WriteLine(); 放在底部。如果您希望用户能够随时按下某个键并使其不断闪烁,那么您将不得不参与多线程,这可能比您感兴趣的要复杂一些。

【讨论】:

【参考方案2】:

首先,我会为此使用Thread.Sleep。休眠你的主线程提供了相当粗糙的用户体验......这是一种快速而肮脏的方法,但不是该方法的真正用途。

这是一个使用计时器闪烁一行文本的快速示例。

using System.Timers;
class Program

    static void Main(string[] aszArgs)
    
        Timer myTimer = new Timer(500);
        myTimer.Elapsed += MyTimer_Elapsed;
        myTimer.Enabled = true;

        //Wait for a key. Or do other work... whatever you want
        Console.ReadKey();
    

    private static bool cleared = true;
    private static void MyTimer_Elapsed(object sender, ElapsedEventArgs e)
    
        if (cleared)
            Console.WriteLine("Flash text");
        else
            Console.Clear();

        cleared = !cleared;
    
  

我在这个例子中使用了System.Timers.Timer,它有一些可靠的文档和例子here。

【讨论】:

【参考方案3】:

您可以像这样以相等的间隔执行一批操作:

using System;
using System.Threading;

namespace ConsoleApp

    class Program
    
        static void Main(string[] args)
        
            new Program().Run();
        

        private void Run()
        
            do
            
                while (!Console.KeyAvailable)
                    this.InvokeWithIntervals(1000,
                                             () => Console.WriteLine("Press any key to continue..."),
                                             () => Console.Clear());
             while (Console.ReadKey(true).Key != ConsoleKey.Escape);
        

        private void InvokeWithIntervals(int interval, params Action[] actions)
        
            foreach(var action in actions)
            
                action.Invoke();
                Thread.Sleep(interval);
            
        
    

【讨论】:

【参考方案4】:

一种稍微不同的方法是使用Stopwatch 类来测量时间,并且只有在我们通过了指定的“闪烁间隔”时才更改文本。

我们可以编写一个方法来执行此操作,它需要一个 string prompt 来显示,一个 TimeSpan interval 指定在闪烁文本之间等待多长时间。

在代码中,我们将捕获光标位置和控制台颜色,启动秒表,然后每次秒表经过interval 指定的时间量时,我们将交换Console.ForegroundColorConsole.BackgroundColor

该方法将执行此操作,直到用户按下一个键,我们将返回给调用者:

private static ConsoleKey FlashPrompt(string prompt, TimeSpan interval)

    // Capture the cursor position and console colors
    var cursorTop = Console.CursorTop;
    var colorOne = Console.ForegroundColor;
    var colorTwo = Console.BackgroundColor;

    // Use a stopwatch to measure time interval
    var stopwach = Stopwatch.StartNew();
    var lastValue = TimeSpan.Zero;

    // Write the initial prompt
    Console.Write(prompt);

    while (!Console.KeyAvailable)
    
        var currentValue = stopwach.Elapsed;

        // Only update text with new color if it's time to change the color
        if (currentValue - lastValue < interval) continue;

        // Capture the current value, swap the colors, and re-write our prompt
        lastValue = currentValue;
        Console.ForegroundColor = Console.ForegroundColor == colorOne 
            ? colorTwo : colorOne;
        Console.BackgroundColor = Console.BackgroundColor == colorOne 
            ? colorTwo : colorOne;
        Console.SetCursorPosition(0, cursorTop);
        Console.Write(prompt);
    

    // Reset colors to where they were when this method was called
    Console.ForegroundColor = colorOne;
    Console.BackgroundColor = colorTwo;

    return Console.ReadKey(true).Key;

现在,在调用方,我们将向其传递文本“按转义键继续”和我们想要等待的时间量(在您的情况下为TimeSpan.FromMilliseconds(500)),然后我们可以无限地调用它@ 987654329@循环,直到用户按下ConsoleKey.Escape

private static void Main()

    // Flash prompt until user presses escape
    while (FlashPrompt("Press escape to continue...", 
        TimeSpan.FromMilliseconds(500)) != ConsoleKey.Escape) ;

    // Code execution continues after they press escape...

这里的好处是您可以重复使用逻辑并可以指定更短或更长的闪存时间。您还可以通过在调用方法之前指定它们来更改“闪烁”的颜色(或者可以编写方法以将它们作为参数)。

例如,试试这个:

private static void Main()

    Console.WriteLine("Hello! The text below will flash red " + 
        "and green once per second until you press [Enter]");

    Console.ForegroundColor = ConsoleColor.Red;
    Console.BackgroundColor = ConsoleColor.Green;

    while (FlashPrompt("Press [Enter] to continue...", 
        TimeSpan.FromSeconds(1)) != ConsoleKey.Enter) ;

    Console.ResetColor();

    // Code will now continue in the original colors

【讨论】:

你忘了提到我需要添加Using System.Diagnostics; 我试图找到一个秒表类并手动添加它,但后来我想通了!谢谢。这很有帮助。【参考方案5】:

我对@9​​87654321@ 进行了改进,这会导致 CPU 使用率过高。我的回答让 CPU 在等待期间处于空闲状态,但需要添加对 System.Windows.Forms 的引用。

private static void Timer_Tick (object sender, EventArgs e)

    ((System.Windows.Forms.Timer)sender).Stop();

private static ConsoleKey FlashPrompt(string prompt, TimeSpan interval)

    // Capture the cursor position and console colors
    var cursorTop = Console.CursorTop;
    var colorOne = Console.ForegroundColor;
    var colorTwo = Console.BackgroundColor;
    
    // Write the initial prompt
    Console.Write(prompt);

    // Set up timer
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
    timer.Tick += Timer_Tick;
    timer.Interval = (int)interval.TotalMilliseconds;
    while (!Console.KeyAvailable)
    
        // Wait the required interval, checking every 100ms
        timer.Start();
        while (!Console.KeyAvailable && timer.Enabled)
        
            Application.DoEvents();
            System.Threading.Thread.Sleep(100);
        

        // Wwap the colors, and re-write our prompt
        Console.ForegroundColor = Console.ForegroundColor == colorOne 
            ? colorTwo : colorOne;
        Console.BackgroundColor = Console.BackgroundColor == colorOne 
            ? colorTwo : colorOne;
        Console.SetCursorPosition(0, cursorTop);
        Console.Write(prompt);
    

    // Reset colors to where they were when this method was called
    Console.ForegroundColor = colorOne;
    Console.BackgroundColor = colorTwo;

    return Console.ReadKey(true).Key;

【讨论】:

以上是关于C# |控制台应用程序 |如何在执行下一行之前让程序等待(以毫秒为单位的时间)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不重新编译的情况下配置我的 C# 项目? [复制]

在 C# 中,我应该如何关闭正在运行的线程(Access DB)?

如何在隐藏控制台的情况下运行 C# 控制台应用程序

C# 控制台日期输入

我如何让java在执行下一行之前等待一秒钟,而不使用try/catch [重复]

如何在后台连续运行 C# 控制台应用程序