3

This is my first attempt at learning classes in any language. I am trying to create a Windows Form Project that is a stop watch. I've created a class that has a StartClock method that starts a stopwatch, I then put the elapsed time into a timespan variable. I then take a elapsedTime string and set it equal to a formatted string with the time span varibles. Code Below.

 public class CStopWatch
{

     Stopwatch sw = new Stopwatch();

    private DateTime startTime;

    private DateTime stopTime;

    private String elapsedTime;

    public String ElapsedTime
    {
        get
        { 
            return elapsedTime; 
        }


    }

     public String StartClock()
     {

         sw.Start();
         TimeSpan ts = sw.Elapsed;
         elapsedTime = String.Format("{0:00}:{1:00}:{2:00}",
        ts.Hours, ts.Minutes, ts.Seconds / 10);
         return elapsedTime;


     }

    public void StopClock()
     {
        // sw.Stop();
     }

}

On the Windows Form I call a new instance of my CStopwatch class and then on the start button click event I start my forms timer, call my StartClock method, and then set my time interval to every second.

In my Timer tick event I set my label to display the elapsed time string variable. When I run this I do not get any errors, but the label does not change. Below is my Windows Form Code.

 public partial class Form1 : Form
{
   // string elapsedTime;

   // public string elapsedTime { get { return elapsedTime; } }

    CStopWatch sw = new CStopWatch();

    public Form1()
    {
        InitializeComponent();
    }

    private void lblTime_Click(object sender, EventArgs e)
    {

    }


    private void btnStart_Click(object sender, EventArgs e)
    {
        timer.Enabled = true;
        sw.StartClock();
        timer.Interval = 1000;

        //Testing without using classes
        /*
        timer.Enabled = true;
        sw.Start();
        timer.Interval = 1000;
        TimeSpan ts = sw.Elapsed;
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}",
        ts.Hours, ts.Minutes, ts.Seconds / 10);
      */

    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void timer_Tick(object sender, EventArgs e)
    {

        lblTime.Text = sw.ElapsedTime;


    }
}

I'm sure I'm missing something or doing something stupid, but all my google fu has not lead me to the answer yet. Thanks in advance.

B.K.
  • 9,982
  • 10
  • 73
  • 105
Lance Hietpas
  • 351
  • 1
  • 5
  • 17

6 Answers6

3

You assign value of variable elapsedTime only once after clicking on Start button. Later on you try to read value from it (using ElapsedTime property) in timer_Tick method however you do not assign new value. Try something like this:

public String ElapsedTime
    {
        get
        { 
            TimeSpan ts = sw.Elapsed;
            return String.Format("{0:00}:{1:00}:{2:00}",
        ts.Hours, ts.Minutes, ts.Seconds / 10);
        }
    }
Valker
  • 58
  • 1
  • 5
  • Thanks! I've change my the code in my class to be below, but it still doesn't seem to b updating. `public String ElapsedTime { get { TimeSpan ts = sw.Elapsed; return String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds / 10); } } public void StartClock() { sw.Start(); }` – Lance Hietpas Mar 26 '16 at 19:16
  • Is "timer_Tick" function being called at all? :) If yes, look at d.moncada anserw. It can be issue with another thread trying to update your GUI. Be aware that only GUI-thread can modify GUI components. – Valker Mar 26 '16 at 19:21
  • Gotcha! Thanks again! – Lance Hietpas Mar 26 '16 at 19:24
1

This is because elapsedTime is set once, then never updated.

public String ElapsedTime
{
    get
    { 
      return String.Format("{0:00}:{1:00}:{2:00}", sw.Elapsed);
    }
}

This should fix it. So elapsedTime declaration and initialization are not useful and can be removed:

public class CStopWatch
{
    Stopwatch sw = new Stopwatch();

    public String ElapsedTime
    {
        get
        { 
            return String.Format("{0:00}:{1:00}:{2:00}", sw.Elapsed);
        }            
    }

    public void StartClock()
    {
        sw.Start();
    }

    public void StopClock()
    {
        sw.Stop();
    }
}
Larry
  • 17,605
  • 9
  • 77
  • 106
1

I believe there are some issues with your current implementation. Update your WinForms code-behind so that StartClock happens after you set the Interval. Also, if the Timer is happening on another Thread, you will want to Invoke the control. Lastly, you need to update the ElapsedTime whenever the Tick occurs.

public partial class Form1 : Form
{
    CStopWatch sw = new CStopWatch();

    public Form1()
    {
        InitializeComponent();
    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        timer.Interval = 1000;
        timer.Enabled = true;

        lblTime.Text = sw.StartClock();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

    }

    private void timer_Tick(object sender, EventArgs e)
    {
        UpdateElapsedTime();

       if (lblTime.InvokeRequired) 
       {
            lblTime.Invoke(new MethodInvoker(() => 
            { 
                lblTime.Text = sw.ElapsedTime;
            }));
       }
    }
}

Then, you can update your CStopWatch class to have include an UpdateElapsedTime method.

public class CStopWatch
{
    private Stopwatch sw = new Stopwatch();
    private DateTime startTime;
    private DateTime stopTime;
    private String elapsedTime;

    public String ElapsedTime
    {
        get
        { 
            return elapsedTime; 
        }
    }

    public String StartClock()
    {
        sw.Start();

        UpdateElapsedTime();

        return ElapsedTime;
    }

    public void UpdateElapsedTime()
    {
        TimeSpan ts = sw.Elapsed;
        ElapsedTime = String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds / 10); 
    }

    public void StopClock()
    {
        sw.Stop();
    }
}
d.moncada
  • 16,900
  • 5
  • 53
  • 82
0

check out this , I think the timer tick event occurs on another thread, that not allowed to update the ui, the link shows solutions depends on which .net version you are using.

Community
  • 1
  • 1
Chen Kinnrot
  • 20,609
  • 17
  • 79
  • 141
0

try the following

timer.Elapsed += OnTimedEvent;
timer.Interval = 1000;
timer.Enabled = true;
sw.StartClock();

Add the following method:

private static void OnTimedEvent(Object source, ElapsedEventArgs e)
    {
        lblTime.Text = string.Format("{0:HH:mm:ss.fff}",e.SignalTime);
    }
Eminem
  • 7,206
  • 15
  • 53
  • 95
0

The problem is that you actually don't update your elapsedTime variable. You can instead use your Stopwatch in ElapsedTime property:

public String ElapsedTime
{
    get
    {
        return string.Format("{0:00}:{1:00}:{2:00}", sw.Elapsed.Hours, sw.Elapsed.Minutes, sw.Elapsed.Seconds / 10);
    }
}

or equivalently (C# 6.0):

public String ElapsedTime => $"{sw.Elapsed.Hours:00}:{sw.Elapsed.Minutes:00}:{sw.Elapsed.Seconds/10:00}";
bottaio
  • 4,963
  • 3
  • 19
  • 43