'Getting Elapsed Time with DispatchTimer to 1 millisecond accuracy

I'm trying to measure the elapsed time in milliseconds between keypress events using a dispatch timer but when declaring a dispatch timer to have an interval of 1 millisecond and then establishing the tick event it doesn't fire every 1 millisecond but somewhere like 10-100 milliseconds (guess). How do I accurately measure time in milliseconds if this tick event doesn't fire on time? I'm doing this in silverlight which doesn't seem to have access to System.Timers. The same seems to happen with System.Threading.Timer.

Here's the basics of the code:

public void StartTimer(object o, RoutedEventArgs sender)
{
    System.Windows.Threading.DispatcherTimer myDispatcherTimer = new  
    System.Windows.Threading.DispatcherTimer();
    myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1); // 1 Milliseconds 
    myDispatcherTimer.Tick += new EventHandler(Each_Tick);
    myDispatcherTimer.Start();
}

// A variable to count with.
int i = 0;

public void Each_Tick(object o, EventArgs sender)
{
    i++;
}

public void keypress(object s, EventArgs args)
{
    label1.contents = i.ToString();
    i = 0;
}

Any ideas?



Solution 1:[1]

The System.Threading timer in Silverlight is only accurate down to about 20ms. Normally you'd want a multimedia timer if you needed better resolution, but you can't access those directly in Silverlight. That said, with some significant tweaking and tradeoffs, I've read that it's possible to get a Silverlight timer that has ~3ms ms accuracy. See the docs referenced here:

Link

Note that I haven't tested all those alternatives myself, but they're worth looking into.

Another alternative is the recently introduced System.Diagnostics.Stopwatch class. Unfortunately, this is only sometimes a high resolution timer, depending on the hardware you're running on. And the MS docs don't specify how they determine whether it's truly high resolution or not, so your only option is to check the IsHighResolution property.

Solution 2:[2]

Start a Stopwatch instead and simply subtract the stopwatch's current elapsed milliseconds from the last elapsed milliseconds (which you need to store in a variable) each time a key is pressed.

    private Stopwatch _stopwatch;
    private int _lastElapsedMs;

    public void StartTimer(object o, RoutedEventArgs sender)
    {
        _lastElapsedMs = 0;
        _stopwatch = Stopwatch.StartNew();
    }

    public void keypress(object s, EventArgs args)
    {
        int elapsedMs = (int)_stopwatch.ElapsedMilliseconds;
        int currentElapsed = (elapsedMs - _lastElapsedMs);

        _lastElapsedMs = elapsedMs;

        label1.contents = currentElapsed.ToString();
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Glorfindel
Solution 2 Tim Lloyd