1

I have a dispatcher timer which has to act like a heartbeat every 500ms and write on a register on an anybus. I have set it with maximal priority:

m_HeartBeatTimer = new DispatcherTimer(DispatcherPriority.Render);

the problem is that when program is running sometimes the interval can enormously get longer up to 19 seconds:

[20/06/2017 17:00:01.182] HeartBeat 1 79

[20/06/2017 17:00:20.669] HeartBeat 0 80

of course there are other timers and other operations but shouldn't the timer be insensitive of those ones?

Is there any way to make it respect the correct timing? thank you

Community
  • 1
  • 1
Luca
  • 918
  • 2
  • 13
  • 30
  • There is certainly something in your program that blocks the UI thread. – Clemens Jun 20 '17 at 15:38
  • The dispatcher timer is not in the ui thread. It's beyond the interface. Any way of setting it regardless of any other task? – Luca Jun 20 '17 at 15:46
  • 1
    DispatcherTimer is executed on the UI thread – Mikko Viitala Jun 20 '17 at 15:54
  • You mean you have another Dispatcher thread than the UI thread? – Clemens Jun 20 '17 at 15:55
  • Yes the ui thread runs on its own. Then I have a library which does the polling/heartbeat on the anybus. Here resides the timer. Is there any means of making a timer as much as run-time as possible? – Luca Jun 20 '17 at 16:01
  • 1
    From the [docs](https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer(v=vs.110).aspx) _Timers are not guaranteed to execute exactly when the time interval occurs, but they are guaranteed to not execute before the time interval occurs._ – Mikko Viitala Jun 20 '17 at 16:06
  • That is fine... but going from 500ms to 19000ms seems too much to me... – Luca Jun 20 '17 at 16:09
  • 1
    I was asking about another *Dispatcher*. If there is no other Dispatcher, the DispatcherTimer is created with affinity to the UI thread's Dispatcher, and its Tick handler is executed in that thread, i.e. the UI thread. Ask yourself why the class is called DispatcherTimer. For what you're trying to do, you may probably better use one of the other timer classes. – Clemens Jun 20 '17 at 16:16
  • 1
    Yes thank you!!! That might be the problem there is another Dispatcher timer doing other things and going with the same interval. Do you think that it might interfere? And if not using a Dispatcher timer should I use a Windows.Forms.Timer?? – Luca Jun 20 '17 at 17:08
  • 2
    That other `DispatchTimer` would most definitely interfere. If both are running on the UI thread, work done on the other timer is going to block both the UI and this timer until it completes. I would use a `System.Threading.Timer` over a `Windows.Forms.Timer` in a WPF application, though I prefer going `async` over both options if possible. – Bradley Uffner Jun 20 '17 at 17:31
  • Ok thanks, any means of setting the priority with it? – Luca Jun 20 '17 at 17:40
  • There *is* an overload for it that accepts a `DispatchPriority`, but that only affects the priority of the timer event within the application's queue, so it may not help you much. Once a timer is executing its code on the UI thread, nothing else on that thread can run until it completes, even it it would be a higher priority, it physically can't run (or even qet queued) until the thread is released by the currently executing code. – Bradley Uffner Jun 20 '17 at 17:51
  • You are still confusing things. It doesn't matter if there is another `DispatcherTimer`. Again, I was asking about another `Dispatcher`. If you did not create another Dispatcher than the one that is implicitly created by the UI thread, all your DispatcherTimers execute on the UI thread. If there is something that blocks the UI thread, be it a Tick handler of another timer or *anything else*, your timer's Tick handler won't be called. – Clemens Jun 20 '17 at 18:04
  • It won't be called even if it's a System.Threading.Timer ?? – Luca Jun 21 '17 at 14:49
  • @Clemens I have not understood: if the ui thread is blocked will also the System.Threading.Timer be blocked? because this is what happens. So if you say that this shouldn't happen I am doing somehting wrong. – Luca Jun 22 '17 at 15:00
  • System.Threading.Timer shouldn't be blocked by the UI thread unless you make a Dispatcher.Invoke call from the timer event. – Clemens Jun 22 '17 at 15:45

1 Answers1

0

.net has several types of timers. The Windows.Forms.Timer and DispatcherTimer both run on the UI thread. They only tick when the UI thread is not busy.. if the UI thread is locked into some task then the tick waits until the task is done.

If you want a true heartbeat then I recommend using System.Threading.Timer instead. This one will tick on a worker thread, so keep that in mind.

private System.Threading.Timer _timer;

private void go()
{
    _timer = new Timer(_ => Timer_Tick(), null, 0, 1000 * 10); //every 10 seconds
}

private void Timer_Tick()
{
  //this is not the main UI thread. Must invoke if you want to interact with the UI
}
Bill Tarbell
  • 4,933
  • 2
  • 32
  • 52
  • 1
    No it's not working alas. Being blocked randomly just as the other timer. – Luca Jun 22 '17 at 14:52
  • I know this is an old thread, but responding regardless as this may help someone else. In regard to the above comment by @Luca, I had the same problem. Even with a timer on a separate thread, it was still misbehaving. I found that running the `Release` rather than the `Debug` version of my program fixed this. It just seems to be an oddity arising from the `Debug` environment. – Reece Jul 28 '23 at 00:26