Reputation: 4339
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
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
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