Stopwatch application starts but won't stop

518 views Asked by At

For some reason I am able to start the stopwatch, but when I try and click the stop button, nothing happens.

I have some background in java programming but I was assigned a project to make a program in a language I didn't know so I picked C#. I have some knowledge about C# but would greatly appreciate if someone can help me out with this problem.

using System;
using Gtk;
using System.Threading;
using System.Diagnostics;
using System.Timers;

public partial class MainWindow: Gtk.Window
{
    Stopwatch stopwatch = new Stopwatch();
    System.Timers.Timer timer  = new System.Timers.Timer();
    bool stopClicked = false;

    public MainWindow () : base (Gtk.WindowType.Toplevel)
    {
        Build ();
    }

    protected void OnDeleteEvent (object sender, DeleteEventArgs a)
    {
        Gtk.Application.Quit ();
        a.RetVal = true;
    }

    protected void OnStartButtonClicked (object sender, EventArgs e)
    {
        Thread thread1 = new Thread(new ThreadStart(Thread1));
        thread1.Start ();
        stopwatch.Start ();
        Console.WriteLine ("Stopwatch started");

        timer.Elapsed += new ElapsedEventHandler (timerTick);
        timer.Interval = 100;
        timer.Enabled = true;
        timer.Start ();
        Console.WriteLine ("Timer started");
    }

    protected void OnStopButtonClicked (object sender, EventArgs e)
    {
        stopClicked = true;
    }

    void timerTick(object sender, EventArgs e)
    {
        timeLabel.Text = stopwatch.Elapsed.ToString ();
        System.Windows.Forms.Application.DoEvents ();
    }

    void Thread1()
    {
        if(stopClicked)
        {
            timeLabel.Text = stopwatch.Elapsed.ToString ();
            timer.Stop ();
            timer.Enabled = false;
            timer.Dispose ();
            Console.WriteLine ("Timer stopped");
            stopwatch.Stop ();
            Console.WriteLine ("Stopwatch stopped");
        }
     }
 }
3

There are 3 answers

2
Hamid Pourjam On

It is because Thread1 is running just once, you should use a busy wait loop to do this something like

void Thread1()
{
    while (true)
    {
        if (stopClicked)
        {
            timeLabel.Text = stopwatch.Elapsed.ToString();
            timer.Stop();
            timer.Enabled = false;
            timer.Dispose();
            Console.WriteLine("Timer stopped");
            stopwatch.Stop();
            Console.WriteLine("Stopwatch stopped");
            break;
        }
        Thread.Sleep(10);
    }
}

but you can move the whole logic to OnStopButtonClicked and there is no need to use threads anymore

protected void OnStopButtonClicked (object sender, EventArgs e)
{
    timeLabel.Text = stopwatch.Elapsed.ToString ();
    timer.Stop ();
    timer.Enabled = false;
    timer.Dispose ();
    Console.WriteLine ("Timer stopped");
    stopwatch.Stop ();
    Console.WriteLine ("Stopwatch stopped");
}
0
Thorsten Dittmar On

Your thread is not doing anything. The thread method only runs once. You need at least a loop to check whether stopClicked is clicked at some point.

void Thread1()
{
    while (!stopClicked)
    {
        Thread.Sleep(100);
    }

    // Rest of the code to finish the timer.
}

Actually I do not quite understand why you need the thread at all. Just stop your timer when the stop button is clicked. No need for a separate thread here. And it causes all kinds of problems.

Also there's no need to do

System.Windows.Forms.Application.DoEvents();

The UI will update when the timer method is left, anyway. And it's not good practise. Also, the System.Timers.Timer is called in a separate thread, so you actually should be getting a cross-thread-exception here.

0
user287107 On

an easy solution would be:

protected void OnStartButtonClicked (object sender, EventArgs e)
{
    stopwatch.Start ();

    // the next 3 lines could also be in the constructor function
    timer = new System.Timers.Timer();
    timer.Elapsed += new ElapsedEventHandler (timerTick);
    timer.Interval = 100;
    timer.Start ();
    Console.WriteLine ("Timer started");
}


protected void OnStopButtonClicked (object sender, EventArgs e)
{
    timer.Stop ();
    stopwatch.Stop ();
    Console.WriteLine ("Timer stopped"); 
}

void timerTick(object sender, EventArgs e)
{
    timeLabel.Text = stopwatch.Elapsed.ToString ();
}