Jules
Jules

Reputation: 4339

Diagnostics.StopWatch time lag in XP but not Win7

ETA: Using Environment.TickCount does not present the same problem.
ETA2: I should add that I don't actually use the Forms.Timer in my app - as this would negate the use of a high frequency timer. I've used it here to simplify the code.

ETA3: I've published a workaround as an answer below.

I'm having problems with the StopWatch class that I'm observing on a laptop with XP but not a different laptop with Win7. Here's the test code:

Public Class FormTest
    Inherits Form

    Private WithEvents Timer1 As System.Windows.Forms.Timer = New System.Windows.Forms.Timer
    Private sw As Stopwatch = New Stopwatch

    Public Sub New()
        Me.Timer1.Interval = 1
    End Sub

    Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
        MyBase.OnClick(e)
        Me.sw.Start()
        Me.Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Me.Text = sw.ElapsedMilliseconds.ToString
        Me.Update()
    End Sub

End Class

On windows 7, checking the ellapsed milliseconds every second, I get something like: 0, 1010, 2030, 3005 ...
On XP, I get something like: 0, 200, 306, 390, 512, ...

That is, it is way off. We're not talking about milliseconds. It's nothing to do with whether the timer is high resolution, as that reports as true. As far as I know it's nothing to do with processor affinity as I've tried setting that to each of the 2 processors.

As I say, I think this is to do with XP, but it could be to do with the different cores - both laptops are, however, intel.

Upvotes: 0

Views: 373

Answers (2)

Jules
Jules

Reputation: 4339

I've solved the problem by using the timeGetTime method instead. The following code is basically the Diagnostics.StopWatch class but with the QueryPerformanceCounter call replaced with timeGetTime.

I haven't fully tested it yet* but, from what I've read, I should be able to make a call to TimeBeginPeriod(1) to achieve resolution in line with the framework stopwatch.

(*If have fully tested it now and it does achieve millisecond accuracy).

If anyone can tell me how to make QueryPerformanceCounter work for XP (if indeed XP is the problem), or detect if there is a problem, I'll un-mark this and mark yours as the answer.

Imports System.Runtime.InteropServices

Friend Class StopWatch

    Private Elapsed As Integer
    Private StartTimeStamp As Integer

    Public Sub Start()
        If Not Me._IsRunning Then
            Me.StartTimeStamp = StopWatch.timeGetTime
            Me._IsRunning = True
        End If
    End Sub

    Public Sub [Stop]()
        If Me.isRunning Then
            Me.Elapsed = (Me.Elapsed + (StopWatch.timeGetTime - Me.StartTimeStamp))
            Me._IsRunning = False
            If (Me.Elapsed < 0) Then
                Me.Elapsed = 0
            End If
        End If
    End Sub

    Public Sub Reset()
        Me.Elapsed = 0
        Me._IsRunning = False
        Me.StartTimeStamp = 0
    End Sub

    Private _IsRunning As Boolean
    Public ReadOnly Property IsRunning() As Boolean
        Get
            Return Me._IsRunning
        End Get
    End Property

    Public ReadOnly Property ElapsedMilliseconds() As Integer
        Get
            Dim elapsed = Me.Elapsed
            If Me._IsRunning Then
                elapsed = (elapsed + (StopWatch.timeGetTime - Me.StartTimeStamp))
            End If
            Return elapsed
        End Get
    End Property

    <DllImport("winmm.dll", SetLastError:=True)> _
    Private Shared Function timeGetTime() As Integer
    End Function

End Class

Upvotes: 0

Anders Abel
Anders Abel

Reputation: 69280

Do you set the interval of the timer anywhere?

To me it looks like they are running with different intervals. The Win7 is roughly fired every second. The XP one looks like it could be fired every 100ms (with a few sample points missed - it's hard to read things that fast).

I can't find any documentation on the default timer interval. If it is undocumented, it could have been changed between OS and .NET framework versions between your machines.

Upvotes: 2

Related Questions