B+: Simple time-reminder without 100% CPU usage?
Blitz3D Forums/Blitz3D Beginners Area/B+: Simple time-reminder without 100% CPU usage?
| ||
Hey guys. (problem stated after code bit..) I'm trying to do a simple program, where you can enter a given number of minutes in a field. It will then remind you when that time is up. If you enter 1, it will remind you after 1 minute. Code: MainWindow=CreateWindow ("Reminder",GraphicsWidth()/2-100,GraphicsHeight()/2-75,200,150,0,5) Global MinField=CreateTextField (10,25,160,20,MainWindow) Global GoButton=CreateButton ("Go !",10,55,60,20,MainWindow) Global counter=0 Global target=0 Global MilTemp=0 Repeat eid=WaitEvent() Select eid Case $803 Exit End Select If EventSource()=GoButton If EventID()=$401 Go() End If End If Forever Function Go() target=Int(TextFieldText(MinField))*60 MilTemp=MilliSecs() Repeat If MilTemp<=(MilliSecs()-1000) Then MilTemp=MilliSecs() If counter=0 Then counter=1 Else counter=counter+1 End If If counter=target Then Notify "Time is up!" : Exit End If Until KeyHit(1) End Function I'll facelift the program, when the code is okay. Here's my problem. While the time is running, I get 100% CPU usage. Isn't that a bit much? Is there some other way to do this, without that much CPU load? |
| ||
Hey again. - I'm also a little worried, that it might not be 100% precise. Any way of ensuring precision? |
| ||
you could do a check for millisecs() > timestarted + timefinished instead of doing a counter. when you set the alarm you make TimeStarted = Millisecs() should be fairly accurate.. |
| ||
instead of target=Int(TextFieldText(MinField))*60 you should make it target=Int(TextFieldText(MinField))*3600 because Millisecs() returns milliseconds, and you checked it against seconds.. ;) |
| ||
Is there some other way to do this, without that much CPU load? Yes. Use CreateTimer() and an event-based system. Suggestion: Create a Timer with 1 Hz (one tick per second) and then on each Timer event ($4001, I think) just add a tick and check to see if however many seconds you want to have passed are passed. As a side effect, your program does not have to halt execution while it's counting. It can continue on doing whatever, and your CPU usage will be very small. Also, don't be worried about precidion if you're only counting in the minutes range. Precision only matter if you're worried about a few milliseconds here and there. |
| ||
Thank you to all of you! ;) Here is a slightly changed code, which works:MainWindow=CreateWindow ("Reminder",GraphicsWidth()/2-100,GraphicsHeight()/2-75,200,150,0,5) Global MinField=CreateTextField (10,25,160,20,MainWindow) Global GoButton=CreateButton ("Go !",10,55,60,20,MainWindow) Global target=0 Global mins=0 Repeat eid=WaitEvent() Select eid Case $803 Exit End Select If EventSource()=GoButton If EventID()=$401 Go() End If End If Forever Function Go() target=MilliSecs()+((Int(TextFieldText(MinField))*60)*1000) Repeat If MilliSecs()>=target Then Notify "Time is up!":Return Delay 150 Forever End Function As you can see, I pre-calculated the target-MilliSecs() number, and then just keep checking to see if it equals this, or if it's bigger than this. The Delay command ensures low CPU usage. Without the Delay thing, it uses 100% CPU consumption. BUT.. A few seconds after I pressed Go!, the "Running" status in Win Task Manager, changes to "Not Responding". But it still works, and it's very precise (150 millisecs off, is okay..). How come, it's "Not Responding"..? |
| ||
the Not responding thing might be because of the way you exit the function Go().. try replacing :Return with :Exit Exit() command exits loops.. then after Forever, place your Return function there.. I don't belive its wise to jump out of a function in a middle of a repeat-forever loop, because of how it handles the resources & such.. |
| ||
Nah, that can't be it, because it gets nowhere near those commands, UNTIL the time is up. ;-) I tried it anyway, and it didn't work. Thanks anyway. ;) I don't get why it's "Not Responding", in a simple Repeat-Forever loop..? Eek.. Maybe it's the Delay command. That command halts execution -> Not Responding.. Can that be it? That would NOT be good, because I use that command, to keep the CPU usage down.. :( |
| ||
[CODE] SecondTimer = CreateTimer(1) target=MilliSecs()+MinutesToWait*60000 repeat WaitTimer(SecondTimer) until MilliSecs()>target [/code] |
| ||
I don't get why it's "Not Responding", in a simple Repeat-Forever loop..? The answer is *because* you're in a repeat-forever loop. You see, the program is busy working between the Repeat and Forever, and you are not allowing it to even pay attention to events that Windows sends to it (like move, focus, resize, close, etc) -- so to Windows, it is unresponsive. This is what I meant up above where I said "your program does not have to halt execution"... I guess I said that wrong. Your program is still executing (of course) but Windows doesn't know about this. What you have to do to fix this is make sure that WaitEvent is called in your loop. Whenever WaitEvent is called, Blitz (behind the scenes) starts looking for Windows event messages that Windows sends to it. You don't see this happen, but it does, and it's what keeps it responsive in Windows. It's also how you get the event messages. I recommend an Event Loop like this: CreateTimer(1) ; Timer that fires an event $4001 once per second Target% = 5 ; 5 seconds -- change this to your textfield number bCounting% = False ; has the user clicked the Go button? tick% = 0 ; how long has it been since the user clicked Go? While WaitEvent() Select EventID() Case $803 : End Case $401 : If EventSource() = BtnButton Then bCounting = True Case $4001 ; Timer event (once per second) If bCounting Then tick = tick + 1 If tick = Target Then bCounting = False tick = 0 Notify "Target reached!" EndIf EndIf End Select Wend |
| ||
its 5:30am here, and i need some sleep.. so i dont know if i undertand right what you want.. but cant u just make a :time = Input ("Enter time (in seconds) : ") Delay time*1000 Print "wake up neo.." ? ps. you cant do anything wile we're waiting.. but i guess it wont eat much cpu.. |
| ||
Thank you to all who tried to help me. And thank you VERY MUCH to soja, for bringing me the help and inspiration, that helped me the most. I finished my program now. Thanks! Get it at: http://bachfire.homepage.dk/btr1.zip |
| ||
And thank you VERY MUCH to soja... Gosh, you're welcome. My pleasure. <blush> =) Say, that's a pretty neat little "Laundry Timer" or "Egg Timer" program (as many people call something like that). I did find a couple small issues, though: 1) When the target is reached, and the notification is displayed, if the user clicks Cancel, the Start button is still shown as deactivated and the Stop button is still activated (even though the status is idle). 2) There's an interesting behavior when the user enters negative numbers... how long do you think it will count? =) (It gets more interesting when you enter very large numbers, like 2^32-1, but that's no big deal...) |
| ||
Thanks again, soja! ;) Yeah, when used negative numbers, it required a patient man to handle the situation.. ;) These issues should now be fixed. Get the updated version here: http://bachfire.homepage.dk/btr11.zip |