1

I am making a console maths project where the user answers multiple maths questions.

I am trying to add a countdown timer but I can't find how to make a timer that will stop once the user answers all the questions;

Does anyone have any idea how to do this?

d51
  • 316
  • 1
  • 6
  • 23
  • 1
    I strongly suggest you use some sort of graphical user interface technology. Doing it in a console app would be an interesting challenge, but a very frustrating one.. If you want some ideas about how to write a complicated console app (alas, it doesn't consider this case), take a look at my answer to: https://stackoverflow.com/questions/52431607/exit-console-app-at-any-time-during-any-input-c – Flydog57 May 05 '20 at 03:11
  • It would be great to understand what you want the timer to actually do. It's unclear what a timer's purpose is that would stop after all of the questions are answered. Is it just that someone has 30 seconds to answer all 10 questions, that sort of thing? – Enigmativity Jan 21 '22 at 04:36
  • I've looked in your code. You're doing some bad things. You should never do `timerThread.Abort()`. Also `while (DateTime.Now < whenToStop) { /* ... */ Thread.Sleep(1000); }` is a terrible idea. – Enigmativity Jan 21 '22 at 04:37

3 Answers3

1

You can quite easy replace your Thread code with a System.Threading.Timer based version.

I refactored your code in your GutHub: https://github.com/CrazyDanyal1414/mathstester.git

public class RunWithTimer
{
    private DateTime _finish { get; set; }
    public bool IsTimeLeft { get=> _finish > DateTime.Now; }

    private System.Threading.Timer _timer = null;

    private void TimerCallback(object state)
    {
        string timeLeft = (_finish - DateTime.Now).ToString(@"hh\:mm\:ss");
        WriteToScreen($"Time Remaining: {timeLeft}", true);
        if (!this.IsTimeLeft)
        {
            _timer.Dispose();
        }
    }
    public RunWithTimer(int numberOfSeconds)
    {
        _finish = DateTime.Now.AddSeconds(numberOfSeconds);
        _timer = new Timer(TimerCallback, null, TimeSpan.Zero, TimeSpan.FromSeconds(1.0));
    }
    public void StopTimer(int numberOfQuestionsLeft)
    {
        if (numberOfQuestionsLeft == 0)
        {
            _timer.Dispose();
        }
    }
}

Ideally your RunWithTimer would implement IDisposable since it holds a variable of IDisposable. You'd then remove the StopTimer code and Dispose() of the it once the questions are finished.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
0

Timers, ProgressBars and similar do not work that well in Console. This addition would be almost trivial in a GUI technology. But doing it in Console requires jumping through hoops. And probably do a major redesign.

The main issue is that you need to be able to receive input, but without blocking code excution. The conventional Console read methods are all blocking to the last. However there is a workaround. A way to wait for input without blocking:

https://stackoverflow.com/a/5620647/3346583

Andreas
  • 5,393
  • 9
  • 44
  • 53
Christopher
  • 9,634
  • 2
  • 17
  • 31
0

This should help you. Though the example is a windows forms app, you can use the Timer class to achieve what you want.

Raju Joseph
  • 493
  • 1
  • 6
  • 13
  • Please do not link to external content without putting the salient parts of that content in your answer itself. You should always write answers that would stand-alone if the link became broken in the future. – Enigmativity Jan 21 '22 at 04:32