Gustav Brock
Gustav at cactus.dk
Wed Feb 11 04:24:04 CST 2009
Hi Terry Your programmers may have to look a bit deeper into this. While I have no reason to doubt the articles of the links from Stuart and John on the hardware limitations, Windows XP behaves a bit clever than stated. Stuart mentions the API call timeBeginPeriod but doesn't show how to use it which is as simple as can be (more on this later). If you are really interested in the millisecond business, not only for timing purposes but also to obtain absolute time, I can recommend the article here: http://www.devx.com/dbzone/Article/39046 A free registration is required to access the page and download. If you download the code with a bunch of functions, you'll find these two: Msec() FormatMsec() The first returns the current time with a resolution of 1 ms and an accuracy of something close. The next formats a date/time value with milliseconds for you to read as VB(A) rounds milliseconds to the second when displaying date/time values. If you create a very simple loop, you are able to create a list of milliseconds from time values with a difference less than 1 ms as the code runs in about 0.5 ms per loop: For n = 0 to 10 : ? FormatMsec(Msec,"i") : Next .996 .997 .997 .998 .998 .998 .999 .999 .000 .001 .001 To obtain this, timeBeginPeriod is called as shown here: <code> Public Function Msec( _ Optional ByVal intTimePart As Integer) _ As Date ' Generates the current time with millisecond resolution. ' ' Returns current (local) date/time including millisecond. ' Parameter intTimePart determines level of returned value: ' 0: Millisecond value only. ' 1: Time value only including milliseconds. ' 2: Full Date/time value including milliseconds. ' None or any other value: Millisecond value only. ' ' 2007-06-05. Cactus Data ApS. CPH. Const cintMsecOnly As Integer = 0 Const cintMsecTime As Integer = 1 Const cintMsecDate As Integer = 2 Static typTime As SYSTEMTIME Static lngMsecInit As Long Dim datMsec As Date Dim datDate As Date Dim intMilliseconds As Integer Dim lngTimeZoneBias As Long Dim lngMsec As Long Dim lngMsecCurrent As Long Dim lngMsecOffset As Long ' Set resolution of timer to 1 ms. timeBeginPeriod 1 lngMsecCurrent = timeGetTime() If lngMsecInit = 0 Or lngMsecCurrent < lngMsecInit Then ' Initialize. ' Get bias for local time zone respecting ' current setting for daylight savings. lngTimeZoneBias = GetLocalTimeZoneBias(False) ' Get current UTC system time. Call GetSystemTime(typTime) intMilliseconds = typTime.wMilliseconds ' Repeat until GetSystemTime retrieves next count of milliseconds. ' Then retrieve and store count of milliseconds from launch. Do Call GetSystemTime(typTime) Loop Until typTime.wMilliseconds <> intMilliseconds lngMsecInit = timeGetTime() ' Adjust UTC to local system time by correcting for time zone bias. typTime.wMinute = typTime.wMinute - lngTimeZoneBias ' Note: typTime may now contain an invalid (zero or negative) minute count. ' However, the minute count is acceptable by TimeSerial(). Else ' Retrieve offset from initial time to current time. lngMsecOffset = lngMsecCurrent - lngMsecInit End If With typTime ' Now, current system time is initial system time corrected for ' time zone bias. lngMsec = (.wMilliseconds + lngMsecOffset) Select Case intTimePart Case cintMsecTime, cintMsecDate ' Calculate the time to add as a date/time value with millisecond resolution. datMsec = lngMsec / 1000 / clngSecondsPerDay ' Add to this the current system time. datDate = datMsec + TimeSerial(.wHour, .wMinute, .wSecond) If intTimePart = cintMsecDate Then ' Add to this the current system date. datDate = datDate + DateSerial(.wYear, .wMonth, .wDay) End If Case Else ' Calculate millisecond part as a date/time value with millisecond resolution. datMsec = (lngMsec Mod 1000) / 1000 / clngSecondsPerDay ' Return millisecond part only. datDate = datMsec End Select End With Msec = datDate End Function </code> As you can see, the function "initiallizes" by running a loop to "sync" the absolute time of a lower 10 ms resolution with the timer with the 1 ms resolution. This is, by the way, a perfect example of something that could be moved to the Initialize method of a class but, for the purpose the functions originally were developed, this was not practical. To run the code you'll need some constants and declarations. These are listed in the module for download to be found here: http://assets.devx.com/sourcecode/AccessMillisecond.ZIP /gustav >>> terry.mace at baesystems.com 11-02-2009 05:35 >>> John, When I run this I get times of 15,31,16,31,16, 109 or some numbers very close to these. Programmers I work with (I'm not one) tell me that while the tick count may be a 1mS interval, Windows XP cannot display time at anywhere near this resolution and effectively time samples, hence the results I'm getting. This operation of Windows (inability to have time to less than 10mS) prevents them from having a Windows based system for their application. Regards Terry Mace Logistics Support Officer & Maintenance Supervisor