22

There is no StopWatch for Silverlight.

What would you use instead of it?

I saw some posts about people saying to create an empty animation and call GetCurrentTime() from the Storyboard class, I couldn't get it to work...

What would you do?

Paulo
  • 7,123
  • 10
  • 37
  • 34
  • 2
    interesting since this page seems to indicate it exists - http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.startnew(v=VS.95).aspx – James Manning Apr 14 '11 at 19:06
  • @James That is indeed very interesting. Either that page is just there by error, or maybe it is coming to SL5. This post suggests that you could reference the WP7 dll and use that Stopwatch class. I haven't tried it though. http://forums.silverlight.net/forums/p/207108/486425.aspx – Oskar May 10 '11 at 10:56
  • 1
    @James, @Oskar: Stopwatch for Silverlight does exist, but only for the XNA Framework. See the Version Information section of your link, and compare that with something like System.Boolean: http://msdn.microsoft.com/en-us/library/system.boolean%28v=VS.95%29.aspx – Luke Woodward May 22 '11 at 07:57

4 Answers4

24

This is what I did. Its simple and worked very well for me:

long before = DateTime.Now.Ticks;
DoTheTaskThatNeedsMeasurement();
long after = DateTime.Now.Ticks;

TimeSpan elapsedTime = new TimeSpan(after - before);
MessageBox.Show(string.Format("Task took {0} milliseconds",
    elapsedTime.TotalMilliseconds));

All you needed to do was keep one long variable holding the total ticks before beginning the target task.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
moonlightdock
  • 1,358
  • 13
  • 14
6

See my watch at here. Source code is here. And two articles about it are here and here. The Silverlight animation model lends itself well to a stopwatch.

alt text http://xmldocs.net/ball2/background.png

<Storyboard x:Name="Run" RepeatBehavior="Forever">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
    Storyboard.TargetName="SecondHand" x:Name="SecondAnimation" 
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" RepeatBehavior="Forever">
    <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
    <SplineDoubleKeyFrame KeyTime="00:01:00" Value="360"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
    Storyboard.TargetName="MinuteHand" 
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" RepeatBehavior="Forever">
    <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
    <SplineDoubleKeyFrame KeyTime="01:00:00" Value="360"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
    Storyboard.TargetName="HourHand" 
    Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" RepeatBehavior="Forever">
    <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
    <SplineDoubleKeyFrame KeyTime="12:00:00" Value="360"/>

and the code to run that storyboard is here:

private void RunWatch()
{
    var time = DateTime.Now;

    Run.Begin();

    Run.Seek(new TimeSpan(time.Hour, time.Minute, time.Second));
}
Michael S. Scherotter
  • 10,715
  • 3
  • 34
  • 57
4

Here is a Stopwatch replacement class that you can add to your project.

Dzmitry Lahoda
  • 939
  • 1
  • 13
  • 34
Bryan Legend
  • 6,790
  • 1
  • 59
  • 60
2

There's a few things you could do with this. The fist is use something like the Environment.TickCount like the person here. However, something that I think may work better is to make use of a DispatcherTimer.

To set up a DispatcherTimer to work like a stopwatch we'll also need an associated TimeSpan representing the time it is run. We can instantiate the DispatcherTimer and set the interval that it times, and the handler for the Tick event.

DispatcherTimer _timer;
TimeSpan _time;
public Page()
{
    InitializeComponent();
    _timer = new DispatcherTimer();

    _timer.Interval = new TimeSpan(0, 0, 0, 0, 10);
    _timer.Tick += new EventHandler(OnTimerTick);
}

In the UI we can create something simple to start and stop our timer, as well as display the stopwatch data:

 <StackPanel>
        <Button Content="Start" x:Name="uiStart" Click="OnStartClick"  />
        <Button Content="Stop" x:Name="uiStop" Click="OnStopClick" />
        <TextBlock x:Name="uiDisplay"/>
 </StackPanel>

Now, all that is left is the event handlers.
The OnTimerTick handler will incrementing and display our stopwatch data.
Our Start handler will take care of initalizing/reinitalizing our TimeSpan, while the Stop handler will just stop the DispatcherTimer.

 void OnTimerTick(object sender, EventArgs e)
 {
     _time = _time.Add(new TimeSpan(0, 0, 0, 0, 10));
     display.Text = _time.ToString();
 }       
 private void OnStartClick(object sender, RoutedEventArgs e)
 {
     _time = new TimeSpan(0,0,0,0,0);
     _timer.Start();  
 }
 private void OnStopClick(object sender, RoutedEventArgs e)
 {
     _timer.Stop();
 }
rmoore
  • 15,162
  • 4
  • 59
  • 59
  • I tried using the same approach, however the result isnt correct. Maybe due to the function overhead or due to hardware, the time in the app runs slower than the actual wall clock. Could u please help and fix this? – letsc Jan 05 '12 at 10:45