Can I extract seconds from Tick Count?
Exactly what is a tick count? Can a tick count be converted to seconds?
In a application a certain event takes place and at the point in time it occurs I save the current tick count. Now later another event takes place. At the point in time of the second event I get the current tick count. What I need to be able to resolve is how many seconds elapsed from the first event to the second event and the only thing I have are the two tick counts. Using Time doesn't work for this situation.
Re: Can I extract seconds from Tick Count?
By tick count I trust you mean the return from GetTickCount Api
Code:
Declare Function GetTickCount Lib "kernel32" Alias "GetTickCount" () As Long
It returns the number of milliseconds that the computers been running (unless it has already looped). I think it returns an unsigned long so it's good for 24.8 days in VB (not tested).
(EndTick - StartTick) / 1000 '<--- should give the number of seconds.
Edit: VB's own Timer function (contrary to popular belief) works to exactly the same accuracy as GetTickCount (~1/64th of a second) it's just a little slower to access.
Re: Can I extract seconds from Tick Count?
Quote:
Originally Posted by Milk
...Edit: VB's own Timer function (contrary to popular belief) works to exactly the same accuracy as GetTickCount (~1/64th of a second) it's just a little slower to access.
I don't want to start a lengthy discussion here but the Timer is affected by other events and hence is only accurate to +/- 40 ms.
Re: Can I extract seconds from Tick Count?
ok :) lets not, but GetTickCount is not accurate to milliseconds (as it's return suggests) it only updates every 1/64th of a second. Perhaps closer to the 1/64th mark than timer, but there's not much in it.
Agreed?
Edit: This test shows them both to be very very similar
Code:
Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Sub Form_Load()
Dim i As Long
For i = 1 To 3000
List1.AddItem Timer & " : " & GetTickCount
Next i
End Sub
If you run down the list you see that they update at the same time.
Timer does take longer to call than GetTickCount, so the Api wins there.
Re: Can I extract seconds from Tick Count?
Milk,
Are you sure it's divide by 1000? Things just arn't computing out right.
Re: Can I extract seconds from Tick Count?
A more accurate method would be to use the QueryPerformanceCounter and QueryPerformanceFrequency APIs, if your computer supports the High Resolution Counter:
eg
Code:
Private Declare Function QueryPerformanceCounter Lib "kernel32" _
(lpPerformanceCount As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" _
(lpFrequency As Currency) As Long
Private curFreq As Currency
Private Sub Command1_Click()
Dim curThen As Currency
Dim curNow As Currency
Dim lngReturn As Long
Dim lngI As Long
Dim sngTime As Single
lngReturn = QueryPerformanceCounter(curThen)
For lngI = 0 To 1000000
a = 10
Next lngI
lngReturn = QueryPerformanceCounter(curNow)
sngTime = (curNow - curThen) * 1000 / curFreq
MsgBox "1 million assignments took " & Format(sngTime, "###0.000") & " milliseconds"
End Sub
Private Sub Form_Load()
Dim lngReturn As Long
lngReturn = QueryPerformanceFrequency(curFreq)
If lngReturn = 0 Then
MsgBox "This Computer does not support the High Resolution Performance Counter"
End If
End Sub
Re: Can I extract seconds from Tick Count?
Quote:
Originally Posted by jmsrickland
Milk,
Are you sure it's divide by 1000? Things just arn't computing out right.
I'm sure ;). How do you mean not right? If your getting a return of 0 it means whatever your measuring is quicker than Gettickcount updates. Unless of course the ticks you are talking about are not the return from GetTickCount.
As Doogle says, use QueryPerformanceCounter for measuring small intervals. It should be noted that QueryPerformanceCounter is not so good for measuring longer periods, can't win 'em all i guess
Re: Can I extract seconds from Tick Count?
Well here is what I am doing.
I have a Timer Control that is fired every 60 seconds. In the Timer event I increment a counter and when the counter equal 5 ( 5 * 60 = 300 = 5 minutes) I call the following API function
GetLastInputInfo
This function returns the tick count of the last time a user did some activity, if any at all, and I compare that tick count with a previous tick count to see if any activity has taken place in the last 5 minutes. So I use the following If clause....
Code:
'
'
Private Sub Timer1_Timer()
'
'
'
If StartTick <> info.tickCount Then
'
' Here if some activity took place
'
If (info.tickCount - StartTick) \ 1000 < 300 Then
Activity = True
Else
Activity = False
End If
'
' Get the new tick value.
'
StartTick = info.tickCount
Else
'
' Here if no activity took place
'
Activity = False
End If
'
'
'
End Sub
Now, let's say the user did something and so the API captures the tick count at the point in time the user did something. In the Timer Event I calculate the number of seconds that has elapsed since the last time the Timer event counter equaled 5 to the tick count when the user did something. So, I would think that the results of the above calculation should never be greater than 300. But my tests show that at times the results are far greater than 300 and as a result causes the variable Activity to be set to False when in fact it should have been set to True.
Re: Can I extract seconds from Tick Count?
Well not being familiar with the API, and not being able to find the VB6 declare anywhere I've had a go with the C#/C++ declare from MSDN.
It seems to be working. Because I'm impatient I've set idle limit to 3 seconds. Which should mean it waits between 3 and 3 + timer.interval to flag Not Active
Code:
Option Explicit
Private Type LASTINPUTINFO
cbSize As Long
dwTime As Long
End Type
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function GetLastInputInfo Lib "user32.dll" (ByRef plii As LASTINPUTINFO) As Long
Private Const MAXIDLE As Long = 3 'Seconds
Private mLastActive As LASTINPUTINFO
Private mNotActive As Boolean
Private Sub Form_Load()
mLastActive.cbSize = 8
Timer1.Interval = 1000
End Sub
Private Sub Timer1_Timer()
GetLastInputInfo mLastActive
mNotActive = GetTickCount - mLastActive.dwTime > MAXIDLE * 1000
If mNotActive Then
Label1.Caption = "Oi! Bum!"
else
Label1.Caption = "Active"
End if
End Sub
Re: Can I extract seconds from Tick Count?
OK, here is the code that I am using....
Code:
Private Declare Function GetLastInputInfo Lib "user32.dll" (inputStructure As inputInfo) As Boolean
Private Type inputInfo
structSize As Long
tickCount As Long
End Type
' The variable that will be passed to the API call and receive the activity report.
Private info As inputInfo
Dim FirstTick As Long
Dim LastTick As Long
Dim TimeCounter As Integer
Const FiveMinutes = 300
Private Sub Timer1_Timer()
Caption = "Elapsed Minutes = " & TimeCounter
If TimeCounter = 5 Then
If Activity Then
Text1.Text = Text1.Text & "User had activity in last 5 minutes" & vbCrLf
Else
Text1.Text = Text1.Text & "No Activity in last 5 minutes" & vbCrLf
End If
TimeCounter = 1
Else
TimeCounter = TimeCounter + 1
End If
End Sub
Private Function Activity() As Boolean
Activity = False
info.structSize = Len(info)
GetLastInputInfo info
Text1.Text = Text1.Text & "Current Time = " & Time & ", FirstTick = " & FirstTick & ", Last Tick = " & info.tickCount & ", Tick Difference In Seconds = " & (info.tickCount - FirstTick) \ 1000 & vbCrLf
l = (info.tickCount - FirstTick) \ 1000
If FirstTick <> info.tickCount Then
If (info.tickCount - FirstTick) \ 1000 < FiveMinutes Then
Activity = True
Else
Activity = False
End If
LastActivityTime = Time
'
' Get the new tick value.
'
FirstTick = info.tickCount
Else
Activity = False
End If
End Function
Private Sub Form_Load()
TimeCounter = 1
info.structSize = Len(info)
GetLastInputInfo info
FirstTick = info.tickCount
Text1.Text = "Application Started at " & Time & ", First Tick Count = " & FirstTick & vbCrLf
End Sub
EDIT:
BTW: I too was able to get it to work down at 3 seconds, even 10 but not five minutes. Maybe 5 minutes is too big of a tick count, I don't know
Re: Can I extract seconds from Tick Count?
Don't you think the way I've done this is a bit simpler?
Set MAXIDLE to 300 and set the Timer.interval to 10000 and you've got a guaranteed Flag at 300 to 310 seconds of inactivity.
Not that we're checking it but the Api should be declared as Long as it's declared as BOOL at MSDN. BOOL is not the same as Boolean. Change it to Long but treat it as Boolean and it will work as it should.
Re: Can I extract seconds from Tick Count?
Milk,
Yes I do. I think your way is totally better. So, if you don't mind I want to use your method. Also, I want to post your example in another thread where I was trying to help someone with this same problem but I will give you the credit for the code.
Re: Can I extract seconds from Tick Count?
No problems at all :thumb: