lndavis23 Posted March 23, 2013 Share Posted March 23, 2013 (edited) I have code which uses several timers. The functions called when these timers go off execute a _Timer_KillTimer for the $timerID passed in. Most of the time this works just fine. Occasionally it does not and the offending timer gets stuck in an infinite loop. Does anyone have any ideas how to fix this? The script is quite long, but the troublesome parts are something like this: ; create a bunch of timers For $i = 1 to 50 step 1 _Timer_SetTimer(0, 100 * $i, "MyTimerFunction") Next ; respond appropriately, then kill timer. Func MyTimerFunction($a, $b, $timerID, $c) If _Timer_KillTimer(0, $timerID) Then ConsoleWrite($timerID & " was killed. " & @CRLF) else ConsoleWrite($timerID & " could not be killed. " & @CRLF) EndIf EndFunc Usually $timerID is killed just fine. However, when it is not it seems to be impossible to kill no matter how many times I re-call _Timer_KillTimer or _Timer_KillAllTimers. Also, it will continue to call MyTimerFunction() endlessly until the script is terminated. Any ideas why the kill function is failing or how to make it work? It seems to happen more often when the interval between timers is short. Thank you for reading. Edited March 23, 2013 by lndavis23 Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2013 Moderators Share Posted March 23, 2013 lndavis23,Welcome to the AutoIt forum. Personally I have always found the _Timer functions to be more trouble than they are worth and use TimerInit/Diff and Adlib to run timing in my scripts. Can you provide an example of how you use _Timer functions in your script - we can perhaps suggest a different way to manage the problem. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
lndavis23 Posted March 23, 2013 Author Share Posted March 23, 2013 Thank you for responding M23. The complete script creates a tool which allows the user to send various series of timed commands, sometimes simultaneously. For example, if the user selects one GUI control, the script might need to start immediately executing Send("1") every 500 ms for a total of 100 times, as well as start executing Send("2") every 750 ms for 50 times starting after a 2 second delay. Meanwhile the script needs to continue monitoring in case the user selects another control. In this case my code would look something like this main() Func main() GUICreate("MyGUI", 150, 500) $Button1 = GUICtrlCreateButton("Button 1", 10, 10, 130, 40) While 1 $msg = GUIGetMsg() if $msg = $Button 1 then Send1and2() WEnd EndFunc Func Send1and2() For $i = 0 to 99 step 1 _Timer_SetTimer(0, 500 * $i, "Send1") Next Sleep(2000) For $i = 0 to 49 _Timer_SetTimer(0, 750 * $i, "Send2") Next EndFunc Func Send1($a, $b, %timerID, $c) Send("1") _Timer_KillTimer($timerID) EndFunc Func Send2($a, $b, %timerID, $c) Send("2") _Timer_KillTimer($timerID) EndFunc What sometimes happens is Send1 will execute well say 98 times, then the 99th will not be killed and Send1 will continue executing infinitum. Typing this out, it seems rather than create 100 one time Send1 timers, it would likely be better to create one timer which is killed after executing 100 times. I'll look into that. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2013 Moderators Share Posted March 23, 2013 (edited) lndavis23, No wonder you had problems if you were creating that many timers! I am sure we can do something better. But firstly, bearing in mind that timing accuracy in AutoIt is not exactly "precise", how precise do your timings have to be? M23 Edited March 23, 2013 by Melba23 Typo Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2013 Moderators Share Posted March 23, 2013 lndavis23,, Try this and see if the timimgs are accurate enough for you: expandcollapse popup#include <GUIConstantsEx.au3> Global $iSend1, $iSend2, $iBegin main() Func main() GUICreate("MyGUI", 150, 150) $Button1 = GUICtrlCreateButton("Button 1", 10, 10, 130, 40) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit Case $Button1 Send1and2() EndSwitch WEnd EndFunc ;==>main Func Send1and2() $iSend1 = 0 $iSend2 = 0 $iBegin = TimerInit() Send1() AdlibRegister("Send1", 500) AdlibRegister("Start_Send2", 1250) EndFunc ;==>Send1and2 Func Send1() $iSend1 += 1 ConsoleWrite("! 1 x " & $iSend1 & " at " & TimerDiff($iBegin) & @CRLF) If $iSend1 = 10 Then AdlibUnRegister("Send1") EndIf EndFunc ;==>Send1 Func Send2() $iSend2 += 1 ConsoleWrite("+ 2 x " & $iSend2 & " at " & TimerDiff($iBegin) & @CRLF) If $iSend2 = 5 Then AdlibUnRegister("Send2") EndIf EndFunc ;==>Send2 Func Start_Send2() Send2() AdlibRegister("Send2", 750) AdlibUnRegister("Start_Send2") EndFunc If they are then we can discuss how to get something like this integrated into your actual script. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
lndavis23 Posted March 23, 2013 Author Share Posted March 23, 2013 (edited) Thanks again. The more precise the timing the better, but there is some room for tolerance. The timing for AdlibRegister is certainly good enough. The implementation challenge is that the user may need to execute overlapping functions. For example, suppose I press the button which starts sending "1" 100 times. Then, after it has executed 50 times, I press it again. In this case I should have seen "1" sent 50 times spaced 500 ms. Then "1" sent 100 times at some rate of twice per 500 ms, then (after the first instance has finished it's hundred) "1" sent another 50 times spaced 500 ms while the second instance finishes. That's the main reason I was using so many timers, though I definitely agree creating fewer would simplify things. Edited March 23, 2013 by lndavis23 Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2013 Moderators Share Posted March 23, 2013 lndavis23,I think we can do something along the lines you require. As you seem to indicate that you will use the same control each time, how do you decide what to send and at what rate - reading it from other controls (combos, inputs, etc) on the GUI perhaps? And do I understand that you want to break into any running functions if the button is pressed before the current cycle ends? That might prove problematic if you were to press it too often and get several interrupted cycles. But before we get into all that, what on earth are you trying to do with this script? Understanding the purpose of the script often suggests the best way to approach the code. And I am really intrigued why you need to Send digits so many times at such regular intervals. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
lndavis23 Posted March 23, 2013 Author Share Posted March 23, 2013 (edited) Yes, what to send is often taken from a variety of other controls on the GUI. The input does not need to break into a currently running function, but it does need to be able to run concurrent with any other timer functions currently running. So in the example before, after pressing Button 1 a function would begin, and then if Button 1 were pressed again the function would begin a second time concurrently with the first instance.The script is actually just an emulator tool for an online flash game by ninjakiwi called Bloons Tower Defense 5. The developers offer a "sandbox" mode to allow players to test custom rounds. Unfortunately this mode of play is largely incomplete for the testing a lot of players want to do. A variety of hotkeys can be sent to trigger events. My script allows users to send multiple repeated hotkeys at set intervals which is a more accurate way to model gameplay. I've posted the complete script as an open source project in the game's forums here: http://archive.ninjakiwi.com/Forum/showthread.php/17437-PROJECT-DC-emulator-for-testing. It can be found in the spoiler at the end of the title post. Edited March 23, 2013 by lndavis23 Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2013 Moderators Share Posted March 23, 2013 lndavis23,Have you read the Forum rules (there is also a link at bottom right of each page) since you registered? If not, I suggest you do so now as what you have explained above makes it sound very much as if this script is not a permitted subject for discussion on this forum. The final decision rests with me - over to you to make the case that I should allow the thread to continue. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
lndavis23 Posted March 23, 2013 Author Share Posted March 23, 2013 (edited) Hmm. Thank you for the link. I'm new to these forums and had not read those. Reading those rules in the strictest sense anything related to any game is off topic. I'd note this is not a bot and the developers of the game in question are aware of the emulator tool and have no objections to it. It's actually being well received on the game's official forums. Regardless that might not matter for this forum. I'll go back and edit my post to remove any offending references. If it matters I feel the question of how to handle a failed _Timer_KillTimer call still holds as a general programming question regardless of application. My intent wasn't really to get help writing my specific script so much as to better understand what is happening and how to mitigate when this function call returns false. I'm thinking something like this may be the way to go, though this is more of a work-around (reducing the number of timers) than a fix: expandcollapse popupGlobal $timerIDArray[1] $timerIDarray[0] = 0 Global $timerCountdownArray[1] $timerCountdownArray[0] = 0 main() Func main() GUICreate("MyGUI", 150, 500) $Button1 = GUICtrlCreateButton("Button 1", 10, 10, 130, 40) While 1 $msg = GUIGetMsg() If $msg = $Button 1 Then Send1and2() WEnd EndFunc Func Send1and2() _ArrayAdd($timerIDArray, _Timer_SetTimer(0, 500, "Send1") _ArrayAdd($timerCountdownArray, 100); _ArrayAdd($timerIDArray, _Timer_SetTimer(0, 750, "Send2") _ArrayAdd($timerCountdownArray, 50); EndFunc Func Send1($a, $b, %timerID, $c) Send("1") $i = _ArraySearch($timerIDArray, $timerID) $timerCountdownArray[$i] -= 1 If $timerCountdownArray[$i] = 0 Then _Timer_KillTimer($timerID) _ArrayDelete($timerIDArray, $i) _ArrayDelete($timerCountdownArray, $i) EndIf EndFunc Func Send2($a, $b, %timerID, $c) Send("2") $i = _ArraySearch($timerIDArray, $timerID) $timerCountdownArray[$i] -= 1 If $timerCountdownArray[$i] = 0 Then _Timer_KillTimer($timerID) _ArrayDelete($timerIDArray, $i) _ArrayDelete($timerCountdownArray, $i) EndIf EndFunc Edit: unfortunately it appears the previous post is now locked and uneditable. Thank you for your time and apologies if I have misused this forum. Edited March 23, 2013 by lndavis23 Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2013 Moderators Share Posted March 23, 2013 lndavis23,You need a certain number of posts before you get "edit" permissons - you should in fact now have it. But please do not go back and edit your posts to remove any game references - I take a very dim view of people doing that to get round the rules. Reading those rules in the strictest sense anything related to any game is off topicI am taken by your point that the underlying question is one of more general interest but unfortunately you are quite correct in your comment. It is immaterial whether the game developers are happy for you to do this - the site owner has set out his prohibitions and I am here to enforce them. As a result I am locking this thread immediately. Although I understand your point about the _Timer-KillTimer failure being of general interest, the entire_Timer_* function range is little used in my experience - partly I am sure because of its unreliability. I would call this very firmly as a Windows, rather than an AutoIt, problem given that all these functions are just simple calls to standard DLLs. As you were setting several hundred timers in your script I am really not very surprised to find that you had some failures given that even one or two such beasts have caused me headaches in the past. For what it is worth, reducing the number of timers as you have done in that final script would be my suggested solution - if you decided that you really did need to use these functions at all. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Recommended Posts