Search code examples
c#winformstimerstopwatch

StopWatch Or Timer


The timer in my opinion is not very accurate when it displays time from its _Tick() Method. I am wanting to show elapsed time in minutes/seconds show the length of time a procedure takes to complete. I have used this with the Timer but have discovered it's calculations are incorrect. Which is why I wanted to ask would a StopWatch be better to show more accurately or is their a separate control that I should be using altogether?

private int timepassed = 0;
private void buttonFourteen_Click(object sender, DragEventArgs e)
{
  timer2.Start();
  var backgroundWorker = new BackgroundWorker();
  backgroundWorker.DoWork += (s, e) =>
  {
    //Lengthy Procedure Goes Here
  };
  backgroundWorker.RunWorkerCompleted += (s, e) =>
  {
    timer2.Stop();
  };
  backgroundWorker.RunWorkerAsync();
}
private void timer2_Tick(object sender, EventArgs e)
{
  timepassed++;
  timedisplay.Text = timepassed.ToString();
}

Solution

  • Here's one way to accomplish this with a stop watch, which should be very accurate:

    private readonly Stopwatch sw = new Stopwatch();
    private readonly System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
    
    public Form1()
    {
        InitializeComponent();
        timer.Tick += timer2_Tick;
    }
    
    private void buttonFourteen_Click(object sender, EventArgs e)
    {
        sw.Restart();
        timer.Start();
        var backgroundWorker = new BackgroundWorker();
    
        // Simulating a 10-second process for testing
        backgroundWorker.DoWork += (s, ea) => Thread.Sleep(TimeSpan.FromSeconds(10));
    
        backgroundWorker.RunWorkerCompleted += (s, ea) => timer.Stop();
        backgroundWorker.RunWorkerAsync();
    }
    
    private void timer2_Tick(object sender, EventArgs e)
    {
        timedisplay.Text = sw.Elapsed.ToString("g");
    
        // Or use a custom time format (you can specify precision as well as
        // delimiters between days, hours, minutes, seconds, and milliseconds):
        // timedisplay.Text = sw.Elapsed.ToString(@"dd\.hh\:mm\:ss\.ff");
    }