Silverlight and Timers

May 15, 2007
No Comments.

I was doing a Silverlight video player for some videos I am doing and I was playing with different ways to show the timeline of a playing video. There are a couple of ways to do this, but in Silverlight 1.0 the typical way was with an animation on a hidden Canvas that you restart over and over to mimic the behavior of a Timer:

<!-- The XAML -->
<Canvas ... >
    <Storyboard x:Name="theTimer">
      <DoubleAnimation Storyboard.TargetName="timerCanvas" 
                       From="0" To="1"  
                       Completed="theTimer_Completed" />

  <Canvas x:Name="timerCanvas" Opacity="0" />


This is hacky to me but it works great in Silverlight 1.0.  I wanted a better Silverlight 1.1 solution so I though, “Hey, its .NET…I’ll use a timer”:

Timer timer = new Timer(new TimerCallback(timerFired), 

And the Handler:

void timerFired(object o)
  // Does not work because I can't update the UI thread from a non UI thread
  progressBar.Width = ((double)videoPlayer.Position.Seconds / 
                       * progressBack.Width;

In Silverlight 1.1 the XAML stack does not support a Dispatcher as such. In fact there is no cross thread messaging at all. Incidently, this has been reported on the Forums and they’ve said that they are going to add a high-performance timer in the Beta timeframe of Silverlight.

But I wanted an answer now and the only one I could find (without resorting to the fake Animation) was the HtmlTimer class. NOTE: The Silverlight team warn against using the HtmlTimer as it is it not high performance enough, but for prototyping Silverlight 1.1, I think its fine. Here’s the HtmlTimer implementation:

// Use a Timer
HtmlTimer timer = new HtmlTimer();
timer.Interval = 100;
timer.Tick += new EventHandler(timer_Tick);

And the Handler:

void timer_Tick(object sender, EventArgs e)
  // Works because the HtmlTimer does not use a separate thread
  // But may be a bit choppy as the timer not very high resolution
  progressBar.Width = ((double)videoPlayer.Position.Seconds / 
                       * progressBack.Width;

Not perfect, but good enough for now…