9

I have a console application and I want to create a countdown timer. This is what I have tried:

    static void Main(string[] args)
    {
        for (int a = 10; a >= 0; a--)
        {
            Console.Write("Generating Preview in {0}", a);
            System.Threading.Thread.Sleep(1000);
            Console.Clear();
        }
    }

This code works in some situations. However, the problem is that it clears the entire console window and cannot be used when there are some characters above the timer.

Leigh
  • 28,765
  • 10
  • 55
  • 103
  • 1
    http://stackoverflow.com/a/888569/1693085 - Rather than `Console.Clear()`, use `\r` in your actual line of text... – John Bustos Aug 01 '13 at 21:30

4 Answers4

17

If you print "\r" to the console the cursor goes back to the beginning of the current line, so this works:

for (int a = 10; a >= 0; a--)
{
    Console.Write("\rGenerating Preview in {0:00}", a);
    System.Threading.Thread.Sleep(1000);
} 
JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 1
    Great answer, but there is a tiny bug. The timer will display 10, 90, 80, 70,... Pad a space at the end of the string and everything will display fine. – Derek W May 06 '14 at 16:15
10

There are two ways i know of doing what you want

1) Use Console.SetCursorPosition();. This is applicable when you are sure of the amount of characters that will be above the timer.

2) Use Console.CursorLeft. This is applicable in all cases.

Code Examples

static void Main(string[] args)
{
   for (int a = 10; a >= 0; a--)
   {
      Console.SetCursorPosition(0,2);
      Console.Write("Generating Preview in {0} ", a);  // Override complete previous contents
      System.Threading.Thread.Sleep(1000);
   }
}

static void Main(string[] args)
{
   Console.Write("Generating Preview in ");
   for (int a = 10; a >= 0; a--)
   {
      Console.CursorLeft = 22;
      Console.Write("{0} ", a );    // Add space to make sure to override previous contents
      System.Threading.Thread.Sleep(1000);
   }
}
Marcus Mangelsdorf
  • 2,852
  • 1
  • 30
  • 40
  • 1
    You could also use `Console.Write( "Generating Preview in {0:00}", a );` to **always display the timer value with a two-digit number**. This way you don't need to add a space at the end to make sure you overwrite the previous two-digit number completely. – Marcus Mangelsdorf May 13 '16 at 16:36
2

Console.SetCursorPosition and related is what you probably looking for. Get current position and set it again back aster every Write/WriteLine call.

Something like:

var origRow = Console.CursorTop;
for (int a = 10; a >= 0; a--)
{
    Console.SetCursorPosition(0, origRow);
    Console.Write("Generating Preview in {0}", a);
    System.Threading.Thread.Sleep(1000);
}
Console.SetCursorPosition(0, origRow);
Console.Write("Generating Preview done.....");
Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
2

One easy trick you can use is to place a \r in your string to return it the cursor to the beginning of the current line:

static void Main(string[] args)
{
    Console.WriteLine("This text stays here");
    for (int a = 10; a >= 0; a--)
    {
        Console.Write("\rGenerating Preview in {0}", a);
        System.Threading.Thread.Sleep(1000);
    }
}
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331