Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DispatchTimer - Prevent the tick event to be triggered if the previous tick is still running

In a Silverlight app, I have a block of code that has to run every 500ms. I am planning o use a DispatcherTimer to achieve this (see code below).

DispatcherTimer dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 0, 0, 500); // 500 Milliseconds
dt.Tick += new EventHandler(dt_Tick);
dt.Start();

However, it may happen that the block of code takes longer than 500ms to execute (the block of code does some webservice calls). How do I make sure that if a call is currently in progress, the DispatcherTimer doesn't trigger another event? What are the options and what is the best way? Using locks?

like image 514
Martin Avatar asked Feb 23 '23 16:02

Martin


2 Answers

The DispatcherTimer only runs on the dispatcher thread - so there's no way you could have two handlers running at the same time. It's possible they'll be queued up and run one directly after another, of course - you should check.

However, you shouldn't be making a web service call in a DispatcherTimer anyway. Do it in a background thread, otherwise you're blocking the UI for updating all the time that you're waiting for the web service. Basically you shouldn't do any long-running work in the UI thread. Use one of the various other timers (e.g. System.Timers.Timer) to regularly perform work on a thread pool thread and use the dispatcher to call back to the UI thread when you've got some data which needs to be displayed on the UI.

Of course, now you've got the potential problem of the new kind of timer firing multiple times concurrently, on multiple threads. One option to avoid this is to set the AutoReset property to false, and just schedule the next timer tick at the end of the current one.

like image 83
Jon Skeet Avatar answered May 10 '23 20:05

Jon Skeet


I would say you skip a tick if it takes too long, otherwise you will get a huge queue because of the lock.

So in the eventhandler say:

if(!busy) {
  busy = true;

  // some code which could take longer than 500 ms

  busy = false;
}
like image 38
Sjoerd Avatar answered May 10 '23 21:05

Sjoerd