Given that Windows is definitely not a real-time OS (some people have tried to make RT versions of NT, with varying degrees of success), and that the very nature of VB makes it an impractical tool for developing real-time applications I think it fair to say that we can never really expect a real-time response in pure Computer Science terms.
However, the requirement here seems to be much simpler: can we get timing accurate to the millisecond?
Well, let's have a look...
Windows has a number of timers and clock counters that you can theoretically use.
Firstly, what is the difference between a timer and a clock counter?
Generally, a timer is something that raises an event at specified intervals or at a given time. For an application, this event might be a callback, a windows message, or a windows event, although at the OS level we might be talking about interrupts
A clock counter is a counter which is increments at a specific 'tick rate' and can be queried for the current number of ticks that it has counted. It is important to realise that the tick rate for most of these clock counters is provided by a timer as described in the previous paragraph.
Why is this important? Because most of the common timers and clock counters are derived from or driven by the system timer - and the system timer (in theory) has a granularity that is a) lower than you might think given the claimed resolution of the various timers and clock counters b) dependant on your OS
Basically the system timer has a resolution of a little over 55ms on W95/98/Me, 16ms on NT 3.5, 10ms on NT4/2000, 10ms or 15ms on XP. I provided a brief explanation of the reasons for this in thread222-495997 (and it is worth pointing out that it is possible to modify this granularity if one is feeling really, really brave; it requires calls to some 'native' kernel functions
All the following timers and clock counters are based off the system timer:
Standard VB timer (claims 1 milliscond resolution)
SetTimer (claims 1 millisecond resolution)
SetWaitableTimer (claims 1 millisecond resolution)
GetLocalTime (claims 1 millisecond resolution)
GetSystemTime (claims 1 millisecond resolution)
GetSystemTimeAsFileTime (claims 100 nanosecond resolution!!)
and therefore their actual resolution is limited to that of the granularity of the system timer.
Indeed, it gets worse than that for the timers we've mentioned, since there is some overhead and latency in raising the event. And if it is a timer which relies on a process receiving a WM_TIMER message before the timer event will get serviced (eg the VB timer, and SetTimer) you can get even more unexpected delays, since WM_TIMER is a) a low priority message b) you can only have one WM_TIMER message in a process's message queue at a time (which means that you can actually lose timer events...)
Of course, in Windows' history there have been requirements for timings more accurate than that provided by the system timer - most notably MIDI in the multimedia extensions, which required an accuracy of real resolution of 1 millisecond. Your VB program can use this accuracy itself by accesing the multimedia timers. The most accurate way to use them is as a clock counter via timeGetTime (or timeGetSystemTime, although this latter has a slightly higher overhead); if you use them as timers (via a callback) then you will suffer a little from the latencies inherent in raising the appropiate callback.
So, using the multimedia timers as clock counters is a pretty good way of getting accurate millisecond elapsed timings.
What if we want better than that? For example, how might we time how much processor time a thread or process has actually taken up, which might often be in the sub-millisecond range? As we have seen the (current) multimedia timers have a maximum resolution of 1 millisecond, so they are clearly no good...
Here's where we introduce the ACPI timer (also known as the Power Management, or PM, clock). It is this real-time clock that normally provides info to the QueryPerformanceFrequency and QueryPerformanceCounter (and is therefore commonly better known to most people as the high performance timer). Typically the ACPI timer runs at 3.579545MHz, giving an accuracy of of about 280 nanoseconds (different hardware with different ACPI timers may give differing results). At this sort of clock resolution the overheads for retrieving the tick count (even though the ACPI timer is optimised for just that) become significant - but they pale into significance when compared to the overheads of VB. Indeed, counting the numer of times we can call QueryPerformanceCounter in a 1 second tight loop shows that the effective accuracy is reduced to about 1.5 microseconds. However, that should be a more than sufficient granularity for doing millisecond reaction timing...