Sign in to follow this  
Followers 0
lndavis23

What to do when _Timer_KillTimer() fails?

11 posts in this topic

#1 ·  Posted (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 by lndavis23

Share this post


Link to post
Share on other sites

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._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

lndavis23,

No wonder you had problems if you were creating that many timers! :o

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? :huh:

M23

Edited 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._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

lndavis23,,

Try this and see if the timimgs are accurate enough for you: ;)

#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._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#6 ·  Posted (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 by lndavis23

Share this post


Link to post
Share on other sites

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. :huh:

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._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#8 ·  Posted (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 by lndavis23

Share this post


Link to post
Share on other sites

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._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#10 ·  Posted (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:

Global $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 by lndavis23

Share this post


Link to post
Share on other sites

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. :naughty:

Reading those rules in the strictest sense anything related to any game is off topic

I 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._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  
Followers 0