I have 2 computers whose time is synchronized through NTP which assures that the time will differ only by a few milliseconds. One of the computers will send a message through TCP to the other one to start a certain c# function at a specified time in the future on both computers.
My question is: How can i trigger a function in C# at a certain time with millisecond precision (or better)? I need to do that in the program code ( so Task Scheduler or other external program will not help). Always cycling in a separate thread to compare current time with target time would not be a good solution i guess.
UPDATE:
DateTime.Now can’t be used in the solution since it has low resolution.
It seems Thread.Sleep() can be forced to have a 1 ms resolution by importing:
[DllImport("winmm.dll", EntryPoint="timeBeginPeriod")]
public static extern uint MM_BeginPeriod(uint uMilliseconds);
and using:
MM_BeginPeriod(1);
To revert to the previous resolution import:
[DllImport("winmm.dll", EntryPoint = "timeEndPeriod")]
public static extern uint MM_EndPeriod(uint uMilliseconds);
and use:
MM_EndPeriod(1);
UPDATE 2:
I tested Thread.Sleep() with many values and it seems that as an average it will tend towards the specified time-span.
Calling Thread.Sleep() only once usually stays around half a ms around the target value time-span so it is pretty precise regarding to a millisecond resolution.
Using the winmm.dll methods timeBeginPeriod and timeEndPeriod seems to have no effect on the accuracy of the result.
SOLUTION:
One method would be to use timeSetEvent(deprecated) or CreateTimerQueueTimer.
Current problem is that both need as a parameter the time left untill function triggers instead of the time at which it should trigger.
So the delay until desired time for the trigger must be calculated but DateTime.Now offers low resolution. I found a class that allows high resolution obtaining of current DateTime.
So now the time left can be calculated with high resolution and be passed as a parameter to CreateTimerQueueTimer.
This should give you one event every millisecond. You can use a stopwatch to measure the elapsed time. Trigger an event on the main UI thread by using invoke so you don’t block the timer.