1
\$\begingroup\$

I am making a C# console maths test where the user answers maths questions.

I am trying to add a timer to the test, I have managed to make a timer but when I run my code it becomes a mess!

Here is some example code:

class Program
{
    public static OtherCode()
    {
        \\*other code for test
    }
    public class Timer
    {
        public static int Timers(int timeLeft)
        {
            do
            {
                Console.Write("\rtimeLeft: {0} ", timeLeft);
                timeLeft--;
                Thread.Sleep(1000);
            } while (timeLeft > 0);
            Console.Write(Environment.NewLine);
            return timeLeft;
        }
    }

    public static void Main(string[] args)
    {
        int numberOfSeconds = 30;
        Thread thread = new Thread(new ThreadStart(() => {
                TimerClass.Timers(numberOfSeconds);
            }));
        thread.Start();

        \\other code
        OtherCode();
    }
}

Here is my full code: https://github.com/CrazyDanyal1414/mathstester

This is what it looks like when I run the code and try to type an answer to a question: enter image description here

As you can see my timer code is overlapping my question code.

If I use Console.SetCursorPosition(), my timer doesn't move but When I try to type an answer to a maths question my code makes me write it on the same line as the timer like so:enter image description here

Any help appreciated!

\$\endgroup\$
2
\$\begingroup\$

Several things:

  • When doing multi-processing and sharing a resource (in this case, the console window), you should use locks to prevent two threads using the same resource at once. This is the source of your problems. When updating the counter you probably need to hold the lock while moving the cursor to the timer, change the timer string, and hold it until you set the cursor back to the bottom of the console. On the other thread you'd have to maintain the lock while reading user input.
  • You don't need to roll-your-own timers. You can use .NET's Timer class. Notice that Thread.Sleep() is not accurate and you're not really counting seconds (even if you roll-your-own than you should probably do it with time deltas and not with thread sleeps).
  • Don't use the Thread class, use the Task Parallel Library class. It'll be much easier. You will need to use Task.Delay instead of Thread.Sleep
  • Notice that you're line-breaking outside of the loop and not inside. Also WriteLine will add a line-break at the end automatically

If you're merely learning the language (I noticed the "beginner" tag) than I suggest you learn the points I've mentioned. They're more important than learning a specific (and somewhat advanced) use case of C# console applications where you change text while accepting user input. I believe it would be easier for you if it would be a simple WPF application instead of a console application.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.