Naaz
Naaz

Reputation: 101

Unable to correctly restart my DispatcherTimer

I am trying to implement a timer in my application with three buttons - Start, Stop and Restart.

The timer starts and stops fine. However, when I click on the restart button it starts from the previous value of seconds and minutes instead of starting at 0 and 0. I can't see what I'm doing wrong as I set seconds and minutes to 0 right in the start of the restart method itself.

eg: First time starts at 0 and goes on to 1, 2, 3. Stops at 3. When I restart, it starts from 2 and goes on to 4, 6... If I restart again it starts at 3 and goes on to 6, 9, 12...

Below is my code:

    public int seconds;
    public int minutes;
    public int hours;

    System.Windows.Threading.DispatcherTimer myTimer = new System.Windows.Threading.DispatcherTimer();

    private void Tick_Timer_Start(object sender, RoutedEventArgs e)
    {
        myTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
        myTimer.Tick += new EventHandler(Each_Tick);
        myTimer.Start();
    }

    private void Tick_Timer_Stop(object sender, RoutedEventArgs e)
    {
        myTimer.Stop();
    }

    private void Tick_Timer_Restart(object sender, RoutedEventArgs e)
    {
        seconds = 0;
        minutes = 0;
        Timertext.Text = "0 minutes : 0 seconds";
        myTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
        myTimer.Tick += new EventHandler(Each_Tick);
        myTimer.Start();

    }

    private void Each_Tick(object o, EventArgs sender)
    {
        seconds = seconds + 1;

        if (seconds < 10 && minutes < 10)
        {
            Timertext.Text =  minutes.ToString() + " minutes : " + seconds.ToString() + " seconds";
        }
        else if (seconds > 59)
        {
            minutes = minutes + 1;
            seconds = 0;
            seconds = seconds + 1;
            Timertext.Text =  minutes.ToString() + " minutes : " + seconds.ToString() + " seconds";
        }
        else
        {
            Timertext.Text =  minutes.ToString() + " minutes : " + seconds.ToString() + " seconds";
        }
    }

Any help will be much appreciated.

Upvotes: 2

Views: 2519

Answers (4)

Clemens
Clemens

Reputation: 128147

All you need to do is to attach the Tick handler only once:

private int seconds;
private int minutes;
private int hours;
private DispatcherTimer myTimer = new DispatcherTimer();

private void Initialize()
{
    myTimer.Interval = TimeSpan.FromMilliseconds(1000);
    myTimer.Tick += Each_Tick;
}

private void Tick_Timer_Start(object sender, RoutedEventArgs e)
{
    myTimer.Start();
}

private void Tick_Timer_Stop(object sender, RoutedEventArgs e)
{
    myTimer.Stop();
}

private void Tick_Timer_Restart(object sender, RoutedEventArgs e)
{
    myTimer.Stop();
    seconds = 0;
    minutes = 0;
    Timertext.Text = "0 minutes : 0 seconds";
    myTimer.Start();
}

private void Each_Tick(object o, EventArgs sender)
{
    ...
}

Even simpler would be a solution where you would only have Start and Stop, without any need for a Restart:

private int seconds;
private int minutes;
private int hours;
private DispatcherTimer myTimer = new DispatcherTimer();

private void Initialize()
{
    myTimer.Interval = TimeSpan.FromMilliseconds(1000);
    myTimer.Tick += Each_Tick;
}

private void Tick_Timer_Start(object sender, RoutedEventArgs e)
{
    myTimer.Stop();
    seconds = 0;
    minutes = 0;
    Timertext.Text = "0 minutes : 0 seconds";
    myTimer.Start();
}

private void Tick_Timer_Stop(object sender, RoutedEventArgs e)
{
    myTimer.Stop();
}

private void Each_Tick(object o, EventArgs sender)
{
    ...
}

Upvotes: 2

GreenEyedAndy
GreenEyedAndy

Reputation: 1525

Your Program will never work as expected! Everytime you click on your Start-Button, you will add a Tickhandler to the Dispatchertimer so you seconds start to increment by 2 then 3 and so on. You must remove the Handler in your Stop and Restart methods!!! Then all is working as expected and you don't have to create new DispatcherTimer in each Restart. By the way the solution of @DeshDeep Singh never carbage collect the old DispatcherTimer cause the EventHandler keeps it from being collected - so his solution brings you a big memory problem.

Here is the working code:

public int seconds;
public int minutes;
public int hours;

System.Windows.Threading.DispatcherTimer myTimer = new System.Windows.Threading.DispatcherTimer();

private void Tick_Timer_Start(object sender, RoutedEventArgs e)
{
    myTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
    myTimer.Tick += Each_Tick;
    myTimer.Start();
}

private void Tick_Timer_Stop(object sender, RoutedEventArgs e)
{
    myTimer.Tick -= Each_Tick;
    myTimer.Stop();
}

private void Tick_Timer_Restart(object sender, RoutedEventArgs e)
{
    myTimer.Tick -= Each_Tick;
    seconds = 0;
    minutes = 0;
    Timertext.Text = "0 minutes : 0 seconds";
    myTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
    myTimer.Tick += new EventHandler(Each_Tick);
    myTimer.Start();
}

private void Each_Tick(object sender, EventArgs e)
{
    seconds = seconds + 1;
    if (seconds < 10 && minutes < 10)
    {
        Timertext.Text = minutes.ToString() + " minutes : " + seconds.ToString() + " seconds";
    }
    else if (seconds > 59)
    {
        minutes = minutes + 1;
        seconds = 0;
        seconds = seconds + 1;
        Timertext.Text = minutes.ToString() + " minutes : " + seconds.ToString() + " seconds";
    }
    else
    {
        Timertext.Text = minutes.ToString() + " minutes : " + seconds.ToString() + " seconds";
    }
}

Upvotes: 3

Bhavin
Bhavin

Reputation: 260

     // put   myTimer.Stop() in Restart Method

   private void Tick_Timer_Restart(object sender, RoutedEventArgs e)
    {
        myTimer.Stop();  // stop timmer here and try
        seconds = 0;
        minutes = 0;
        Timertext.Text = "0 minutes : 0 seconds";
        myTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
        myTimer.Tick += new EventHandler(Each_Tick);
        myTimer.Start();

    }

Upvotes: 0

DeshDeep Singh
DeshDeep Singh

Reputation: 1863

since the timer is not reset, do this:

private void Tick_Timer_Restart(object sender, RoutedEventArgs e)
    {
        myTimer = new System.Windows.Threading.DispatcherTimer();

        seconds = 0;
        minutes = 0;
        Timertext.Text = "0 minutes : 0 seconds";
        myTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
        myTimer.Tick += new EventHandler(Each_Tick);
        myTimer.Start();

    }

Upvotes: 1

Related Questions