S
Scott McNair
Hi,
I'm trying to create a hi-resolution timer for an application that I'm
working on which needs to be sensitive to at least 10ms. I'd like to
have it mimic the built-in MS timer as much as possible, mainly for ease
of code re-use.
I've found several examples of how to use QueryPerformanceCounter and
QueryPerformanceFrequency to get high-precision time, and I've written
something that works fine for single iterations, but when the timer
starts to repeat itself, the app gets bogged down. I realize it's
bogging down due to recursion, but that's sort of the nature of the beast
with a timer.
Does anybody have a suggestion for how I can recurse elegantly, or
barring that, some good example code for how to implement a hi-res timer
that's MS-like?
My current code is attached:
Class HiResTimer
Declare Function QueryPerformanceCounter Lib "Kernel32" (ByRef X As
Long) As Short
Declare Function QueryPerformanceFrequency Lib "Kernel32" (ByRef X As
Long) As Short
Private iEnabled As Boolean = False
Private StartCount As Long = 0
Private CurrentCount As Long = 0
Private Frequency As Long = 0
Private iInterval As Long = 0
Private Overhead As Long = 0
Public Interval As Long = 1000
Public Property Enabled() As Boolean
Get
Return iEnabled
End Get
Set(ByVal value As Boolean)
iEnabled = value
RaiseEvent EnabledEvent()
End Set
End Property
Public Event Tick()
Private Event EnabledEvent()
Public Sub New()
If (QueryPerformanceCounter(StartCount) = 0) Then
Throw New HiResTimerException()
End If
If (QueryPerformanceCounter(CurrentCount) = 0) Then
Throw New HiResTimerException()
End If
' calculate the time just to call start and end
Overhead = (CurrentCount - StartCount)
End Sub
Private Sub EnabledSub() Handles Me.EnabledEvent
If iEnabled = True Then
'Get the interval in terms of microseconds
iInterval = Interval / 1000
If (QueryPerformanceCounter(StartCount) = 0) Then
Throw New HiResTimerException()
End If
If (QueryPerformanceCounter(CurrentCount) = 0) Then
Throw New HiResTimerException()
End If
QueryPerformanceFrequency(Frequency)
While ((CurrentCount - StartCount - Overhead) / Frequency) <
iInterval
QueryPerformanceCounter(CurrentCount)
End While
RaiseEvent Tick()
RaiseEvent EnabledEvent()
End If
End Sub
End Class
Public Class HiResTimerException
Inherits System.ApplicationException
Overrides ReadOnly Property Message() As String
Get
Return "HiResTimer: QueryPerformanceCounter[Kernel32]
returned 0"
End Get
End Property
End Class
I'm trying to create a hi-resolution timer for an application that I'm
working on which needs to be sensitive to at least 10ms. I'd like to
have it mimic the built-in MS timer as much as possible, mainly for ease
of code re-use.
I've found several examples of how to use QueryPerformanceCounter and
QueryPerformanceFrequency to get high-precision time, and I've written
something that works fine for single iterations, but when the timer
starts to repeat itself, the app gets bogged down. I realize it's
bogging down due to recursion, but that's sort of the nature of the beast
with a timer.
Does anybody have a suggestion for how I can recurse elegantly, or
barring that, some good example code for how to implement a hi-res timer
that's MS-like?
My current code is attached:
Class HiResTimer
Declare Function QueryPerformanceCounter Lib "Kernel32" (ByRef X As
Long) As Short
Declare Function QueryPerformanceFrequency Lib "Kernel32" (ByRef X As
Long) As Short
Private iEnabled As Boolean = False
Private StartCount As Long = 0
Private CurrentCount As Long = 0
Private Frequency As Long = 0
Private iInterval As Long = 0
Private Overhead As Long = 0
Public Interval As Long = 1000
Public Property Enabled() As Boolean
Get
Return iEnabled
End Get
Set(ByVal value As Boolean)
iEnabled = value
RaiseEvent EnabledEvent()
End Set
End Property
Public Event Tick()
Private Event EnabledEvent()
Public Sub New()
If (QueryPerformanceCounter(StartCount) = 0) Then
Throw New HiResTimerException()
End If
If (QueryPerformanceCounter(CurrentCount) = 0) Then
Throw New HiResTimerException()
End If
' calculate the time just to call start and end
Overhead = (CurrentCount - StartCount)
End Sub
Private Sub EnabledSub() Handles Me.EnabledEvent
If iEnabled = True Then
'Get the interval in terms of microseconds
iInterval = Interval / 1000
If (QueryPerformanceCounter(StartCount) = 0) Then
Throw New HiResTimerException()
End If
If (QueryPerformanceCounter(CurrentCount) = 0) Then
Throw New HiResTimerException()
End If
QueryPerformanceFrequency(Frequency)
While ((CurrentCount - StartCount - Overhead) / Frequency) <
iInterval
QueryPerformanceCounter(CurrentCount)
End While
RaiseEvent Tick()
RaiseEvent EnabledEvent()
End If
End Sub
End Class
Public Class HiResTimerException
Inherits System.ApplicationException
Overrides ReadOnly Property Message() As String
Get
Return "HiResTimer: QueryPerformanceCounter[Kernel32]
returned 0"
End Get
End Property
End Class