The most reliable way I could find is to restart the timer in the callback. Thus, the callback is not interrupted when active.
Timer timer = new Timer(TimerCallback, null, 500, 0); private void TimerCallback(Object o) { scan(); scand.WaitOne(); timer.Change(500, 0); }
timer.Change redistributes the timer.
Note. I removed the repetition while the timer started.
By the way: I deleted GC.Collect() , because in most cases I find this bad practice and useless.
In addition, you can get the time at the beginning of the method (use Stopwatch ) and calculate the required time delta for timer transmission. Edit:
Timer timer = new Timer(TimerCallback, null, 500, 0); Stopwatch stopwatch = Stopwatch.StartNew(); private void TimerCallback(Object o) { var entered = stopwatch.ElapsedMilliseconds; scan(); scand.WaitOne(); var duration = stopwatch.ElapsedMilliseconds - entered; var delay = Math.Max(0, 500 - duration); timer.Change(delay, 0); }
Thus, the callback will be called after 500 ms minus the time required to perform the scan functions. Tune in this way and you can remove Sleep from the scan.
The reason for the double callback in your code is probably because the timer is making a callback in another thread when the first thread is still making a callback.
Another solution might not be to use a timer at all. Just cycle and use a stopwatch to calculate the period of time for sleep:
private void Scan() { while(scanning) { var entered = stopwatch.ElapsedMilliseconds; scan(); scand.WaitOne(); var duration = stopwatch.ElapsedMilliseconds - entered; var delay = Math.Max(0, 500 - duration); Thread.Sleep(delay); } }
Make sure you call this method in a separate thread (you can use Task)