Stopwatch for Silverlight

Silverlight 2 does not have an implementation of the .NET Framework’s Stopwatch class (from the System.Diagnostics namespace).  The Stopwatch class can be used for measuring time durations quite accurately, and it can be useful for basic performance profiling or as a simple timer mechanism.  However, this functionality is just not available to a Silverlight application, which is something that I needed, so I wrote an equivalent Stopwatch class in C# that can be used with Silverlight. The code listing is at the end of this post and the class also supports resuming of measurements for cumulative time intervals, which is something that is not supported by the implementation of Jason Jarrett that I initially considered using; to resume the timer, you just call the Start method again after a previous Stop (without calling Reset), exactly as you would with the default .NET implementation.

As far as the resolution of the alternative Stopwatch is concerned, it is not a high resolution timer and is only as accurate as the DateTime structure for the platform on which the Silverlight application is running.  Unfortunately the resolution of the DateTime structure comes without any guarantees from Microsoft, so the worst case scenarios can be bad. This does not seem to be a problem with Silverlight 2 on Windows Vista, which is what I used, but perhaps this is an issue with the Macintosh or Linux implementations (feel free to comment).  I suspect this would likely be a problem with Silverlight for Windows Mobile, since (as far as I recall) the DateTime resolution has always been only full seconds on the Windows CE and Windows Mobile platforms that I have worked with.  (The presentation of Amit Chopra and Giorgio Sardo from Microsoft at PDC2008 mentioned Q1 of 2009 for the public CTP of Silverlight 2 for Mobile, so we should be able to know soon enough.)  Perhaps a future version of this Stopwatch class could use the System.Environment.TickCount property instead of relying on the present underlying DateTime.Ticks mechanism; the former I noticed is more accurate than DateTime for XNA applications using the .NET Compact Framework on the Microsoft Zune.

using System;
namespace TiaanDotCom.Samples.Silverlight
{
public class Stopwatch
{
public static readonly bool IsHighResolution = false;
public static readonly long Frequency = TimeSpan.TicksPerSecond;

public TimeSpan Elapsed
{
get
{
if (!this.StartUtc.HasValue)
{
return TimeSpan.Zero;
}
if (!this.EndUtc.HasValue)
{
return (DateTime.UtcNow - this.StartUtc.Value);
}
return (this.EndUtc.Value - this.StartUtc.Value);
}
}

public long ElapsedMilliseconds
{
get
{
return this.ElapsedTicks / TimeSpan.TicksPerMillisecond;
}
}
public long ElapsedTicks { get { return this.Elapsed.Ticks; } }
public bool IsRunning { get; private set; }
private DateTime? StartUtc { get; set; }
private DateTime? EndUtc { get; set; }

public static long GetTimestamp()
{
return DateTime.UtcNow.Ticks;
}

public void Reset()
{
Stop();
this.EndUtc = null;
this.StartUtc = null;
}

public void Start()
{
if (this.IsRunning)
{
return;
}
if ((this.StartUtc.HasValue) &&
(this.EndUtc.HasValue))
{
// Resume the timer from its previous state
this.StartUtc = this.StartUtc.Value +
(DateTime.UtcNow - this.EndUtc.Value);
}
else
{
// Start a new time-interval from scratch
this.StartUtc = DateTime.UtcNow;
}
this.IsRunning = true;
this.EndUtc = null;
}

public void Stop()
{
if (this.IsRunning)
{
this.IsRunning = false;
this.EndUtc = DateTime.UtcNow;
}
}

public static Stopwatch StartNew()
{
var stopwatch = new Stopwatch();
stopwatch.Start();
return stopwatch;
}
}
}

Download: Stopwatch-Silverlight-cs.txt (2.34 KB)

Comments

Stopwatch

Tiaan,

Thanks! Your post stil helped me in Silverlight 4 where i spend way to much time with working with inaccurate DateTime.Now.Ticks!

Found a better solution yet?

Greetings

Sander

Re: Stopwatch

It is good to hear somebody found the code useful! :) Thanks for letting me know it also works with Silverlight 4. But no, I haven’t looked for something better since the original post (and it doesn’t feel like it can be 2.5 years later already). Of course, I’d be interested to know if there is a better way.