2

I'm implementing a countdown in my app

private async void Window_Activated(object sender, WindowActivatedEventArgs args)
{       
  dispatcherTimer = new DispatcherTimer();
  dispatcherTimer.Tick += dispatcherTimer_Tick;
  dispatcherTimer.Interval = new TimeSpan(0,1,0);
  dispatcherTimer.Start();     
}

private void dispatcherTimer_Tick(object sender, object e)
{
  TimeSpan timeSpan = new TimeSpan(blockTime.Hours, blockTime.Minutes, blockTime.Seconds);

  if (timeSpan != TimeSpan.Zero)
  {
    timeSpan = timeSpan.Subtract(TimeSpan.FromMinutes(1));
    Countdown_TexBlock.Text = String.Format("{0}:{1}", timeSpan.Hours, timeSpan.Minutes);
    dispatcherTimer.Start();   
  }     
  else
  {
    dispatcherTimer.Stop();
  }
}

The code works but only one time For example I put 15 minutes in the blocktime (the time that the countdown will be running) after a minute the countdown.text would be 0:14. So only works after the first minute

Is not supposed to be restarted with dispatcher.start()

Ahmet Firat Keler
  • 2,603
  • 2
  • 11
  • 22
KelvinJPS
  • 69
  • 6

1 Answers1

1

In the code that you posted, I don't see the blockTime variable being changed to any other value than it has in the beginning. This means that on every tick of dispatchTimer the value of the timeSpan.Subtract expression will always evaluate to the same 14 minutes. In your code, that 14 minutes is assigned to a local vaiable that is disposed when the tick is over. This gives the appearance that the dispatchTimer has stopped issuing Tick when it hasn't.


Here's what I ran that works as expected (for testing, I changed the minutes to seconds to make it observable in a reasonable time).

public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
        // Create the dispatch timer ONCE
        dispatcherTimer = new DispatcherTimer();
        dispatcherTimer.Tick += DispatcherTimer_Tick;
        dispatcherTimer.Interval = TimeSpan.FromSeconds(1);

        // This will restart the timer every
        // time the window is activated
        this.Activated += (sender, e) =>
        {
            startOrRestartDispatchTimer();
        };
    }

    private void startOrRestartDispatchTimer()
    {
        dispatcherTimer.Stop(); // If already running
        blockTime = TimeSpan.FromSeconds(15);
        Countdown_TexBlock.Text = blockTime.ToString();
        dispatcherTimer.Start();
    }

    private void DispatcherTimer_Tick(object sender, object e)
    {
        if (blockTime > TimeSpan.Zero)
        {
            blockTime = blockTime.Subtract(TimeSpan.FromSeconds(1));
            Countdown_TexBlock.Text = blockTime.ToString();
            if (blockTime == TimeSpan.Zero)
            {
                Countdown_TexBlock.Text = "Done";
                dispatcherTimer.Stop();
            }
        }
    }

    TimeSpan blockTime = TimeSpan.FromSeconds(15);

    private DispatcherTimer dispatcherTimer;

    // This will restart the timer when the button is clicked.
    private void buttonRestart_Click(object sender, RoutedEventArgs e) =>
        startOrRestartDispatchTimer();
}
IVSoftware
  • 5,732
  • 2
  • 12
  • 23
  • thanks for your help, but I'm still having a problem after a couple of minutes , the timer start getting faster (the seconds last less) – KelvinJPS Jul 24 '22 at 22:28
  • Sorry I missed that! In your original code, the dispatch timer gets a new event _every time_ the window is activated and I copied that more or less. What _should_ happen is the timer gets created (and the event subscribed to) only **once**. I edited the code to show this and will push that commit. – IVSoftware Jul 24 '22 at 22:58
  • Plz let me know if there is still any problem. [Clone](https://github.com/IVSoftware/dispatcher-timer-restart.git). – IVSoftware Jul 25 '22 at 00:09
  • 1
    it's working smoothly, thanks for your help you only not solve my problem you also explained to me. – KelvinJPS Jul 25 '22 at 14:44