kvdveer schreef op 04 March 2003 @ 22:08:
In dat topic wordt uitgelegd dat het simpelweg _onmogelijk_ is om betrouwbaar te timen op intervals <1/18 seconden.
Er zijn wel oplossingen. Die zijn niet nauwkeurig, maar ze voldoen wel. De belangrijkste zijn sg. high-resolution multimedia timers. In windows zijn die te vinden in winmm.dll. Hoe windows het doet is 'geheim', maar wine lost het op met een thread die een proces een trap geeft zodra een bepaald aantal instructies is verlopen na de laatste clocktick.
ten eerste is die topic echt onzin, ze hebben er duidelijk geen verstand van. Leuk dat de VB timer 'slechts' 1/18e seconde precisie heeft, maar dat heeft verder weinig met windows te maken, meer met VB zelf
QueryPerformanceCounter () is iig precieser dan 1 ms, zeker op winNT kernels. Verder kun je ook nog ver komen met GetThreadTimes (), wat verschillende tijden van een bepaalde thread geeft. Ook deze tijden zijn heel erg precies.
Sleep () is kwa milliseconde precisie niet betrouwbaar, omdat als een thread wakker wordt hij nog niet direct aan de beurt komt, aangezien de thread die op dat moment bezig is de rest van z'n timeslice gewoon afmaakt. De prioriteit van de huidige thread omhoog zetten werkt echter wel.
Maar goed, volgens mij gaat het hier niet om precisie, maar meer om het feit dat ie z'n app wil delayen zonder dat de message loop gestopt wordt. Dan kan er idd gebruik worden gemaakt van de WM_TIMER message (zie SetTimer ())
Een andere oplossing is een waitable timer maken, en dan wachten tot die timer verstreken is, maar wel ondertussen window messages afvangen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| bool wait (DWORD msecs)
{
struct ScopedHandle // helper struct for closing the handle
{
HANDLE handle;
ScopedHandle (HANDLE pHandle) : handle (pHandle) { }
~ScopedHandle () { CloseHandle (handle); }
operator HANDLE () { return handle; }
};
ScopedHandle timer = CreateWaitableTimer (NULL, TRUE, NULL);
LARGE_INTEGER waitTime;
// time in 100 nanosecond intervals, relative time:
waitTime.QuadPart = (__int64)msecs * -10000;
SetWaitableTimer (timer, &waitTime, 0, NULL, NULL, FALSE);
while (true)
{
DWORD r = MsgWaitForMultipleObjects (1, &timer, FALSE, INFINITE, QS_ALLINPUT);
if (r == WAIT_OBJECT_0 + 1) // message in queue
{
MSG msg;
if (!GetMessage (&msg, NULL, 0, 0)) // quit message?
return false;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
else
return true;
}
} |
retourneert true als er gewacht is, en false als de tijd nog niet verstreken was maar er een quit message was binnen gekomen
niet getest enzo