1

I searched a few links for Timer Control for both Windows and WPF applications but I would appreciate some advice on my situation...

As I'm using WPF it seems initial options are either System.Windows.Threading.DispatcherTimer or System.Diagnostics.Stopwatch

What I need to achieve is for each WPF DocumentPanel to request an update from an external API at a defined interval between typically 100ms Min - anytime Max with the interval unique to each DocumentPanel. Eg DP1 could be 100ms, DP2 could be 20,000ms etc.

Normally my app would start with 1 DocumentPanel but the user can expand panels without limit so it's the users judgement on CPU ability and speed of app.

Criteria include:

  1. Multiple DocumentPanels - Typically 1 - 20 minimum but any advice on scalability is welcome.

  2. Variable event interval (Iv) (Minimum event interval 100ms - Max < 1day)

  3. Accuracy - 1ms (cannot have interval below (Iv)ms under ANY circumstances, over is not as much concern but needs to be be within several ms) EDIT: 1ms is not strictly a requirement but average (Iv) must be maintained over a short timescale.

  4. Each DocumentPanel must display live date/time but produce events based on set interval

I'm really after help with design consideration rather than actual code at the moment as WPF is confusing matters for me.

Currently, I'm verging towards using a single instance of System.Diagnostics.Stopwatch and allow each panel to act on the stopwatch event whether the interval time has been reached.

Can anyone advise?

Thank you O

  • 2
    1ms resolution - good luck. It think the only way to get this is use a timer to get close, then busy-wait until the stopwatch (high-resolution performance counter) clicks over. – lc. Aug 31 '12 at 00:15
  • Perhaps it doesn't have to have 1ms accuracy if I can find a way to ensure (Iv) ms intervals is never less than (Iv)- Is that possible? –  Aug 31 '12 at 00:18
  • @lc. true. Windows is on it's back before 1 msec can be achieved. – kenny Aug 31 '12 at 00:19
  • @ooo timers and GUIs are a code smell. Why do you need timers? Can't you base the code of UI or hardware/device events? – kenny Aug 31 '12 at 00:22
  • @kenny - Timer is required to maintain API requirements, updating live data as quickly as possible. It's critical the data is live. –  Aug 31 '12 at 00:26
  • 1
    Where's your live data coming from? Polling should be a *last* resort. – kenny Aug 31 '12 at 00:29
  • http://stackoverflow.com/questions/2875178/how-long-is-the-time-frame-between-context-switches-on-windows – kenny Aug 31 '12 at 00:30
  • @kenny - `Polling should be a last resort` - I agree but this is a crap API that doesn't use Push technology. (Also well known!) –  Aug 31 '12 at 00:39
  • @kenny I don't see the issue in the right situation. If you need to read today's temperature every 10 seconds then what else are you going to use besides a timer? An event from a timer is little different to a mouse click event as far as the GUI is concerned. – MikeKulls Aug 31 '12 at 05:54
  • @MikeKulls the key is, right situation. It isn't clear so I'm heeding a warning. As a contractor, I've seen too many GUI messes that are behind schedule and have timers run around each other. Perhaps I'm over-reacting ;) – kenny Aug 31 '12 at 11:12
  • @Kenny fair enough, I agree that if there is some event that could be used to get the data changes then that should definately be used in preference to timers. – MikeKulls Sep 03 '12 at 00:43

4 Answers4

1

its better to use just one System.Windows.Threading.DispatcherTimer with 100ms as ticks, then use Tags to determine its own interval, for example you can use

struct IntervalComparer
{
     int myinterval; //the individual update interval (300ms for example)
     int currentinterval;
     public IntervalComparer(int myinterval)
    {
            this.myinterval=myinterval;
            this.currentinterval=0;
    }

        public void TickMe()
        {
            currentinterval++;
        }

        public void ResetkMe()
        {
            currentinterval = 0;
        }

        public bool CanIUpdate()
        {
            return myinterval == currentinterval;
        }
}

on the creation

.... Form_Loaded....
{
 .....
      mypanel=new Panel();
      mypanel.Tag= new IntervalComparer(2); // 2 * 100ms
 .....
}

.... Timer_Tick....
{
   ....
   (mypanel.Tag as IntervalComparer).TickMe();
    if((mypanel.Tag as IntervalComparer).CanIUpdate())
     {
       UpdateMyPanel();//your update method 
       (mypanel.Tag as IntervalComparer).ResetMe();
     }

   ....
}
S3ddi9
  • 2,121
  • 2
  • 20
  • 34
  • I would suggest that instead of using multiples of 100ms you can still use the actual ms required. If it is, say, 95ms then it will round to 100ms most of the time but round down enough so that *on average* it fires at 95ms intervals. This is assuming that the number of times it fires per hour is important. – MikeKulls Aug 31 '12 at 00:27
  • yes, also you can tick your timer on a different thread then call the UpdateMyPanel on the main_UI_Thread – S3ddi9 Aug 31 '12 at 00:31
1

Generally in a case like this I would have a single timer which when then check for the elapsed time for each DocumentPanel. I'm guessing 100% accuracy is not critical, if they select 999ms then they won't notice if you main timer fires every 50ms so can only give them increments of 50ms. Windows does not give that sort of accuracy anyway, I learnt this when trying to trigger a flash once.

MikeKulls
  • 2,979
  • 2
  • 25
  • 30
1

I've used the following approach to achieve something similar in a Silverlight app:

Single timer which ticks at a small interval (you're discretion, but would need to be lower than the lowest supported update interval), and then have each DocumentPanel subscribe to this timer's tick event.

When the tick event is fired, each DocumentPanel would then determine if an update is required based on it's update frequency (E.G. (last update - now ) > interval).

There's a comparison of some timer classes here:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

DispatcherTimer isn't mentioned, but the important difference between DispatcherTimer and System.Timers.Timer is:

If a System.Timers.Timer is used in a WPF application, it is worth noting that the System.Timers.Timer runs on a different thread then the user interface (UI) thread. In order to access objects on the user interface (UI) thread, it is necessary to post the operation onto the Dispatcher of the user interface (UI) thread using Invoke or BeginInvoke. Reasons for using a DispatcherTimer opposed to a System.Timers.Timer are that the DispatcherTimer runs on the same thread as the Dispatcher and a DispatcherPriority can be set on the DispatcherTimer.

(from http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer.aspx).

Without knowing how you are currently handling UI updates and how you're program is structured, it's hard to say which timer you should use.

I'm not hugely familiar with the using the StopWatch, but my opinion is (after reading http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx) that using a single StopWatch isn't something that is particularly suited to this problem

wdavo
  • 5,070
  • 1
  • 19
  • 20
0

use can inherit from DocumentPanel if you need the Tag property & for more encapsulation

    class UpdatableDocumentPanel : DocumentPanel
    {
        public int myinterval { get; set; }//the individual update interval (300ms for example)
        int currentinterval;


        public void Update()
        {

            currentinterval++;

            if (myinterval == currentinterval)
            {
                currentinterval = 0;
                UpdateMyPanelMethod();
            }
        }
    }

and

 .... Form_Loaded....
 {
  .....
  mypanel.myinterval = 2; // 2 * 100ms
  .....
 }

 .... Timer_Tick....
 {
    ....
   mypanel.Update(); // simply
    ....
 }
S3ddi9
  • 2,121
  • 2
  • 20
  • 34