我如何更新C#Windows控制台应用程序中的当前行?

在C#中构建Windows控制台应用程序时,是否可以写入控制台而无需扩展当前行或转至新行? 例如,如果我想显示一个百分比来表示一个进程完成的距离,我只想更新与游标在同一行上的值,而不必将每个百分比都放在一个新行上。

这可以通过“标准”C#控制台应用程序完成吗?


如果您仅在控制台上打印"r" ,则光标会返回到当前行的开头,然后您可以重写它。 这应该可以做到这一点:

for(int i = 0; i < 100; ++i)
{
    Console.Write("r{0}%   ", i);
}

注意数字后面的几个空格,以确保之前的内容被删除。
另外请注意使用Write()而不是WriteLine()因为您不想在行尾添加“ n”。


您可以使用Console.SetCursorPosition设置光标位置,然后在当前位置写入。

这是一个显示简单的“微调”的例子:

static void Main(string[] args)
{
    var spin = new ConsoleSpinner();
    Console.Write("Working....");
    while (true) 
    {
        spin.Turn();
    }
}

public class ConsoleSpinner
{
    int counter;

    public void Turn()
    {
        counter++;        
        switch (counter % 4)
        {
            case 0: Console.Write("/"); counter = 0; break;
            case 1: Console.Write("-"); break;
            case 2: Console.Write(""); break;
            case 3: Console.Write("|"); break;
        }
        Thread.Sleep(100);
        Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
    }
}

请注意,您必须确保使用新的输出或空白覆盖任何现有的输出。

更新:由于有人批评该示例仅将光标移回一个字符,我将添加以澄清:使用SetCursorPosition可以将光标设置到控制台窗口中的任何位置。

Console.SetCursorPosition(0, Console.CursorTop);

将光标设置到当前行的开头(或者可以直接使用Console.CursorLeft = 0 )。


到目前为止,我们有三个相互竞争的方法来解决这个问题:

Console.Write("r{0}   ", value);                      // Option 1: carriage return
Console.Write("bbbbb{0}", value);                 // Option 2: backspace
{                                                      // Option 3 in two parts:
    Console.SetCursorPosition(0, Console.CursorTop);   // - Move cursor
    Console.Write(value);                              // - Rewrite
}

我一直使用Console.CursorLeft = 0 ,这是第三个选项的变体,所以我决定做一些测试。 以下是我使用的代码:

public static void CursorTest()
{
    int testsize = 1000000;

    Console.WriteLine("Testing cursor position");
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < testsize; i++)
    {
        Console.Write("rCounting: {0}     ", i);
    }
    sw.Stop();
    Console.WriteLine("nTime using r: {0}", sw.ElapsedMilliseconds);

    sw.Reset();
    sw.Start();
    int top = Console.CursorTop;
    for (int i = 0; i < testsize; i++)
    {
        Console.SetCursorPosition(0, top);        
        Console.Write("Counting: {0}     ", i);
    }
    sw.Stop();
    Console.WriteLine("nTime using CursorLeft: {0}", sw.ElapsedMilliseconds);

    sw.Reset();
    sw.Start();
    Console.Write("Counting:          ");
    for (int i = 0; i < testsize; i++)
    {        
        Console.Write("bbbbbbbb{0,8}", i);
    }

    sw.Stop();
    Console.WriteLine("nTime using b: {0}", sw.ElapsedMilliseconds);
}

在我的机器上,我得到以下结果:

  • 退格: 25.0秒
  • 马车回归: 28.7秒
  • SetCursorPosition: 49.7秒
  • 另外, SetCursorPosition引起了明显的闪烁,我没有观察到任何一种选择。 所以,道德是尽可能使用退后或回车谢谢教我更快的方式来做到这一点,所以!


    更新 :在注释中,Joel建议SetCursorPosition在移动距离方面是恒定的,而其他方法是线性的。 进一步的测试证实了这种情况, 时间不变,速度缓慢仍然很慢。 在我的测试中,向控制台写入一长串退格比SetCursorPosition快,直到60个字符左右。 因此,用于替换短于60个字符(或大约60个字符)的行的部分更快, 并且它不闪烁,所以我将支持 b通过 r和SetCursorPosition最初认可。

    链接地址: http://www.djcxy.com/p/50567.html

    上一篇: How can I update the current line in a C# Windows Console App?

    下一篇: How to run a C# console application with the console hidden