C# High Resolution Timer
Timing is important for lots of the software that runs our modern world. Sometimes the timing needs to be very precise and at very small intervals. Fortunately, the Microsoft Windows Operating System (OS) has supported a high resolution timer for some time. A .NET program can access a high resolution timer via the Stopwatch
class. This tutorial provides an overview of the Stopwatch class and a demo program in C#. The C# high resolution timer example provided here helps learn about precision timing for .NET programs.
Windows and Real Time
Windows was made orginally made for office based Personal Computers (PCs). Yet grew to run servers as well as the desktop and laptop computers. Windows is used to successfully run high performance data centres and to control industrial processes, even though it is not a real time operating systems (RTOS). Why can Windows be used to run time critical processes?
It all depends on how fast something needs to be controlled, and how accurate the timing needs to be. If the software on Windows is running fast enough, and the timing requirements do not need to be 100% accurate all the time, just most of the time, then Windows can be very good at handling a time sensitive task.
Windows, Hardware and Timing
Windows is not developed in isolation from the PC hardware. Microsoft works with hardware and the hardware manufacturers to bring PC improvements to market. Microsoft has a Windows Hardware Compatibility Program to ensure that Windows is properly supported by computers. Microsoft's Hardware Compatibility Specification includes the requirement for a high-precision event timer. Alongside the use of a high resolution timer, the Central Processing Unit (CPU) in computers has exceeded gigahertz (GHz) speeds since the early 2000's (1GHz being one thousand million cycles per second). Therefore, PC hardware is able to support high resolution timing.
On of the common problems with reliable timing in Windows was due to the OS needing to access slow hard disks. There would be noticeable pauses due to hard disk accesses. Now that Solid State Drives (SSDs) have supplanted mechanical drives that issue has reduced. Plus, PCs having more memory, which reduces the need to page memory to and from disk.
A high precision timer, GHz CPUs and SSDs means that Windows PCs are very fast devices. There is no excuse for a Windows computer not to be able to handle millisecond timing, most of the time.
Using the .NET Stopwatch Class
With the .NET Stopwatch class measuring time intervals is straightforward. Start by creating an instance of Stopwatch (using System.Diagnostics;
):
Stopwatch sw = new Stopwatch();
There is a property to determine if a high resolution timer is present, otherwise timing resolution is in the milliseconds:
if (Stopwatch.IsHighResolution)
{
LstStatus.Items.Add("Using the system's high-resolution performance counter.");
}
The frequency of the stopwatch can be read:
long frequency = Stopwatch.Frequency;
LstStatus.Items.Add(string.Format("Timer frequency in ticks per second = {0}",frequency));
One modern PCs the C# Stopwatch class gives a timer resolution down to a few hundred nanoseconds (see the table later in the article).
long nanosecPerTick = (1000L * 1000L * 1000L) / frequency;
LstStatus.Items.Add(string.Format("Timer is accurate to within {0} nanoseconds",nanosecPerTick));
There are methods to start and stop the stopwatch, and to check if it is running:
private void ButStart_Click(object sender, EventArgs e)
{
if (sw.IsRunning)
{
LstStatus.Items.Add("Stopwatch is already running");
ButStop.Enabled = true;
}
else
{
sw.Start();
LstStatus.Items.Add("Stopwatch started");
ButStop.Enabled = true;
ButStart.Enabled = false;
}
}
private void ButStop_Click(object sender, EventArgs e)
{
if (!sw.IsRunning)
{
LstStatus.Items.Add("Stopwatch is already stopped");
ButStart.Enabled = true;
}
else
{
sw.Stop();
LstStatus.Items.Add("Stopwatch stopped");
ButStart.Enabled = true;
ButStop.Enabled = false;
}
}
The stopwatch can be restarted and reset.
private void ButRestart_Click(object sender, EventArgs e)
{
sw.Restart();
ButStop.Enabled = true;
ButStart.Enabled = false;
LstStatus.Items.Add("Stopwatch restarted.");
}
private void ButReset_Click(object sender, EventArgs e)
{
sw.Reset();
LstStatus.Items.Add("Stopwatch reset.");
ButStop.Enabled = false;
ButStart.Enabled = true;
}
An finally, of course, reading the elapsed time and elaspsed milliseconds, and measuring the high resolution ticks:
private void ButRead_Click(object sender, EventArgs e)
{
LstStatus.Items.Add(sw.Elapsed.ToString());
}
private void ButReadMilli_Click(object sender, EventArgs e)
{
LstStatus.Items.Add(sw.ElapsedMilliseconds.ToString());
}
private void ButReadTicks_Click(object sender, EventArgs e)
{
LstStatus.Items.Add(sw.ElapsedTicks.ToString());
}
The source code to test the .NET high resolution timer, as a C# project, is available on GitHub in the Test-Stopwatch-Class repository and here on Tek Eye in dotnet-stopwatch.zip, which also includes the project as a compiled Windows executable (StopWatchTest.exe).
Table of .NET Stopwatch High Precision Timing Resolutions
Note: Stopwatch class resolution from a variety of Windows PCs.
CPU | Ticks Per Second | Resolution in Nanoseconds | PC |
---|---|---|---|
i7-4770 3.4 GHz | 3312657 | 301 | Medion Desktop |
i5-2500K 3.3 GHz | 3215348 | 311 | Unbranded Desktop |
i5-3470 3.2 GHz | 3118046 | 320 | HP Desktop |
i7-6820HQ 2.7 GHz | 2648476 | 377 | Dell Laptop |
i5-M560 2.67 GHz | 2597656 | 384 | Toshiba Laptop |
i5-6200U 2.3 GHz | 2343747 | 426 | Dell XPS Laptop |
i5-4200U 1.6 GHz | 2240909 | 446 | Asus Laptop |
See Also
- Timing with the Stopwatch demo in Measuring Code Execution Time in C#
- Bettering the default timer component for High Speed Regular Events in C#
- For a full list of the articles on Tek Eye see the website's index.
Author:Daniel S. Fowler Published: