'High resolution timer in C#
Is there a high resolution timer that raises an event each time the timer elapses, just like the System.Timer class? I need a high resolution timer to Elapse every ms.
I keep running into posts that explain that the Stopwatch can measure high resolutions, but I don't want to measure time, I want to create an interval of 1 ms.
Is there something in .NET or am I going to write my own high res timer?
Solution 1:[1]
I couldn't get Mike's solution to work and created a basic wrapper around Windows multi media timer based on this codeproject article https://www.codeproject.com/Articles/17474/Timer-surprises-and-how-to-avoid-them
public class WinMMWrapper
{
[DllImport("WinMM.dll", SetLastError = true)]
public static extern uint timeSetEvent(int msDelay, int msResolution,
TimerEventHandler handler, ref int userCtx, int eventType);
public delegate void TimerEventHandler(uint id, uint msg, ref int userCtx,
int rsv1, int rsv2);
public enum TimerEventType
{
OneTime = 0,
Repeating = 1
}
private readonly Action _elapsedAction;
private readonly int _elapsedMs;
private readonly int _resolutionMs;
private readonly TimerEventType _timerEventType;
private readonly TimerEventHandler _timerEventHandler;
public WinMMWrapper(int elapsedMs, int resolutionMs, TimerEventType timerEventType, Action elapsedAction)
{
_elapsedMs = elapsedMs;
_resolutionMs = resolutionMs;
_timerEventType = timerEventType;
_elapsedAction = elapsedAction;
_timerEventHandler = TickHandler;
}
public uint StartElapsedTimer()
{
var myData = 1; //dummy data
return timeSetEvent(_elapsedMs, _resolutionMs / 10, _timerEventHandler, ref myData, (int)_timerEventType);
}
private void TickHandler(uint id, uint msg, ref int userctx, int rsv1, int rsv2)
{
_elapsedAction();
}
}
Here's an example how to use it
class Program
{
static void Main(string[] args)
{
var timer = new WinMMWrapper(100, 25, WinMMWrapper.TimerEventType.Repeating, () =>
{
Console.WriteLine($"Timer elapsed {DateTime.UtcNow:o}");
});
timer.StartElapsedTimer();
Console.ReadKey();
}
}
The output looks like this
Update 2021-11-19: add TimerEventHandler class member per chris's comment.
Solution 2:[2]
There is an option: use Thread.Sleep(0). Attempt to call Thread.Sleep(1) or employ a System.Threading.Timer would always come down to system timer resolution. Depending on one is probably not the best idea, at the end of the day you app might be just not allowed to call timeBeginPeriod(...) from winmm.dll.
Following code can resolve down to +/- 10ns (0.10ms) on my dev machine (i7q) and could be higher. It would put a solid load on one of your CPU cores pushing its use up to 100%. No actual OS slowdown would happen, the code surrenders most of its CPU time quantum by calling Thread.Sleep as early as possible:
var requiredDelayMs = 0.1;
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
while (true)
{
if (sw.Elapsed.TotalMilliseconds >= requiredDelayMs)
{
// call your timer routine
}
Thread.Sleep(0); // setting at least 1 here would involve a timer which we don't want to
}
For the more comprehensive implementation see my other answer
Solution 3:[3]
Precision-Timer.NET
https://github.com/HypsyNZ/Precision-Timer.NET https://www.nuget.org/packages/PrecisionTimer.NET/
A High Precision .NET timer that doesn't kill your CPU or get Garbage Collected.
Its designed to be as easy to use as any other .NET timer.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 |

