Hi there, I'm new here!
I hope you can help me with this :)
Well, im programming a text bassed game in C++ and I have the following issue:
Between every text i have a dormir(time in ms) function which basically do this:
It Sleeps while i is minor than x and it's not pressed any key.
But I dont know why, this takes a long, i mean:
dormir(1000) should be 1 second
but it spends more time sleeping (Sometimes, it is not something stable)
1 2 3 4 5 6 7
void Personaje::dormir(int x){
int i = 0;
do{
i++;
Sleep(1); //1ms
}while(i<x && !kbhit()); //Stop sleeping when i reach x and !kbh
}
I dont know if there is another solution for this or another way to program this, i've researched a lot and this is the only way i think you can "stop" a sleep.
In my experience, if you set dwMilliseconds to a value greater than 0 but less than one tick (e.g. Sleep(1);), the thread will sleep for at least one tick. So if one tick is 1/64 second (15.625ms), and you Sleep(1);, your thread will (in my experience) sleep for at least 15.625ms. On a server with Windows Server 2003 Enterprise x64 Edition, 1000 Sleep(1); calls take 15.625 seconds (exactly 1000 ticks). 1000 Sleep(15) calls on the same server takes 15.625 seconds as well.
Here dormir_1() is your function, and dormir_2() is a modified function which can handle whole seconds.
Ouput on my PC
Test_1 : 1 secs
time taken = 1.953 secs
Test_2 : 1 secs
time taken = 1.000 secs
Test_1 : 2 secs
time taken = 3.906 secs
Test_2 : 2 secs
time taken = 2.000 secs
Test_1 : 3 secs
time taken = 5.922 secs
Test_2 : 3 secs
time taken = 3.000 secs
The use of Sleep() and kbhit() (or _kbhit()) says you're working with Windows; this isn't a generic solution.
While you can't stop a Sleep() call, you could use WaitForSingleObject() to wait on a keyboard input with a timeout value. But this would require more involved code.
PS If you do just want to dormir for periods of the order of seconds, then you can probably Sleep a bit longer that "1 msec" each time. Maybe 10 or even 20 msec?
The code you point at doesn't run correctly as-is for me when I run it from Visual Studio. The iskeypressed() function returns immediately so the intended countdown does not run.
The problem is due to a pending FOCUS_EVENT on the console input queue. Using ReadConsoleInput to clear the queue (if not empty) at program startup fixes the problem.
The problem is not there when you run the program directly from a command prompt. But it is if you "start" the program.
Yes, that version of iskeypressed() returns if any input is waiting in the input queue. So the user program has to clear the input queue, either by using ReadConsoleInput() to drain the events or by using cin before calling iskeypressed().
Sorry, I did not expect it to be run by double-clicking.
(A more advanced version if iskeypressed() would also use PeekConsoleInput() to look ahead for any key presses.)
This measures processor time (instead of elapsed wall clock time).
In the posted code, it appears to give results very close to what was expected because there are no other threads in the process which use processor resources, and because the only running thread was never taken off the processor (there were no other threads in a ready state waiting for processor to become available.)