Stopwatch vs. using System.DateTime.Now for timing events
As per MSDN:
The Stopwatch measures elapsed time by counting timer ticks in the underlying timer mechanism. If the installed hardware and operating system support a high-resolution performance counter, then the Stopwatch class uses that counter to measure elapsed time. Otherwise, the Stopwatch class uses the system timer to measure elapsed time. Use the Frequency and IsHighResolution fields to determine the precision and resolution of the Stopwatch timing implementation.
It uses a higher resolution / precision than DateTime.Now
.
You can also check out these related links:
Environment.TickCount vs DateTime.Now
Is DateTime.Now the best way to measure a function's performance?
DateTime
is good enough for precision to the second probably but anything beyond that I would recommend StopWatch
.
Using Stopwatch timer versus DateTime comparisons every 1 second?
The two solutions are equivalent unless you want very high precision: Stopwatch
will use a high precision system timer if available and falls back to DateTime
if not. To address your concerns:
Stopwatch
does NOT use a separate thread. It just reads the system ticks (high or low precision) and does some math for you.DateTime
is a struct so creating a new instance every second should be cheap and put zero pressure on the GC.
I'd use the Stopwatch
because it gives me the elapsed time for free. :)
Is DateTime.Now the best way to measure a function's performance?
No, it's not. Use the Stopwatch (in System.Diagnostics
)
Stopwatch sw = Stopwatch.StartNew();
PerformWork();
sw.Stop();
Console.WriteLine("Time taken: {0}ms", sw.Elapsed.TotalMilliseconds);
Stopwatch automatically checks for the existence of high-precision timers.
It is worth mentioning that DateTime.Now
often is quite a bit slower than DateTime.UtcNow
due to the work that has to be done with timezones, DST and such.
DateTime.UtcNow typically has a resolution of 15 ms. See John Chapman's blog post about DateTime.Now
precision for a great summary.
Interesting trivia: The stopwatch falls back on DateTime.UtcNow
if your hardware doesn't support a high frequency counter. You can check to see if Stopwatch uses hardware to achieve high precision by looking at the static field Stopwatch.IsHighResolution.
DateTime and Stopwatch value comparison
The chances of the elapsed time being exactly the same as the required time - down to the tick - are tiny.
Instead, you should see whether at least the right amount of time has passed:
if (myStopwatch.Elapsed >= workDt.TimeOfDay)
However, the place that you're checking that is inappropriate - you're checking just after starting the timer. Shouldn't you be checking it in the timer tick event?
.NET Stopwatch - performance penalty
The Stopwatch
isn't doing anything between the calls to Start
and Stop
... It just stores the current timestamp (via QueryPerformanceCounter
) when you start it, and compare it to the current timestamp when you stop it. So there is no reason it could affect the performance of your code, at least not significantly. Stopwatch
was designed specifically for accurate time measurements, so you can be sure it is thoroughly optimized. It is also much more accurate than comparing successive values of DateTime.Now
. ...
DateTime class as Stopwatch
As others have said, part of the problem is that you're trying to execute a hard loop inside the same thread that's responsible for updating the UI. Instead of using a loop like this, it's better to use a Timer
, because the timer will run in a different thread so your UI will remain responsive.
The Timer
has an Interval
property that defines how often it executes a task. In our case it will be updating the textbox text. I've set this value to 100 milliseconds in the code below. The timer also has a Tick
event that will execute every time the Interval elapses. Inside this event is where we put the code to update the textbox text.
We should should use a Stopwatch
to measure elapsed time, because that's what it was built for. The DateTime
object is great for holding dates, but it's not as accurate for measuring time.
A stopwatch has a Start
and a Stop
method that we can call from the button click event, so inside that event all we have to do is first check if the stopwatch is running. If it is, then we Stop it. If it isn't, then we Start it.
Putting these ideas together, your code could look something like this:
// At the top of your file, you'll need this to access the Timer:
using System.Windows.Forms;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static Stopwatch stopwatch = new Stopwatch();
private static readonly Timer Timer = new Timer { Interval = 100 };
private void Form1_Load(object sender, EventArgs e)
{
btnStartStop.Text = "Start";
txtVrijeme.Text = stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.ff");
Timer.Tick += Timer_Tick; // This hooks up an event handler for the Tick event
}
// This code executes every {Timer.Interval} millisecond when the timer is running
private void Timer_Tick(object sender, EventArgs e)
{
txtVrijeme.Text = stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.ff");
}
// This method handles the button click. It changes the button text and starts
// or stops the stopwatch, depending on whether the stopwatch is running
private void btnStartStop_Click(object sender, EventArgs e)
{
if (stopwatch.IsRunning)
{
stopwatch.Stop();
Timer.Stop();
btnStartStop.Text = "Start";
}
else
{
Timer.Start();
stopwatch.Start();
btnStartStop.Text = "Stop";
}
}
}
Calculate duration using Date.Time.Now in C#
to accurately measure elapsed time, use StopWatch class:
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Thread.Sleep(10000);
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
// Format and display the TimeSpan value.
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
Console.WriteLine("RunTime " + elapsedTime);
difference between Stopwatch.ElapsedMilliseconds and (stopDateTime - startDateTime).TotalMilliseconds
Stopwatch
is more precised than the calculation of (stop - start).TotalMilliseconds
.
Check this post on SO.
Related Topics
Is There a Reason Image.Fromfile Throws an Outofmemoryexception for an Invalid Image Format
Why Does "Abcd".Startswith("") Return True
Opening New Window in Mvvm Wpf
Starting Tasks in Foreach Loop Uses Value of Last Item
Frombody String Parameter Is Giving Null
Convert Any Object to a Byte[]
Thread Safe C# Singleton Pattern
An Object Reference Is Required to Access Non-Static Member
What Is the Equivalent of the Java Bigdecimal Class in C#
Row_Number Over (Partition by Xxx) in Linq
Centering Controls Within a Form in .Net (Winforms)
How to Add Assembly References in Visual Studio Code
Why Does the Equals Implementation for Anonymous Types Compare Fields