Can't stop Timer object from instance Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
josemaloco
Posts: 2
Joined: 29 May 2019, 03:33

Can't stop Timer object from instance

29 May 2019, 04:40

Hello, I have a script that presses certain numpad keys, but with the idea of learning and trying to make the remapping code as minimalistic as possible, I tried to make it slightly more Object oriented.
I use a timer class which manages the periodicity of keypresses, and then store each of their instances into an array for future use, but the problem is that Im unable to stop them after. Let me explain with some of the stripped code:

When I press F2, it calls a function that sends the keys

Code: Select all

; #Warn  ; Enable warnings to assist with detecting common errors.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

global timerArray

F2::
	beginMacro("test_macro")
	return
	
test_macro(){
	sendKey("1", 500)	
}

sendKey(varKey, period)
{
	global timerArray
	
	numpadKey := "Numpad" . varKey
	send, {%numpadKey%}
	
	if (period > 0){
		timerArray.Push(new Timer(period, "sendNumpadKey", varKey))
	}
}

sendNumpadKey(number){
	sendKey(number, 0)
}
You may have noticed the variable timerArray. Thats where Im storing the instances of the arbitrary number of Timers I may create, so I can reference them later and turn them off when needed.

This is the timer class

Code: Select all

class SelfDeletingTimer {
	__New(timer, fn, params*) {
		this.fn := IsObject(fn) ? fn : Func(fn)
		this.params := params
		SetTimer % this, % timer
	}
	Call() {
		this.fn.Call(this.params*)
	}
	
	Delete(){
		SetTimer % this, Delete
	}
	
}
When I press F2 again it calls a function to stop the previously created timers:

Code: Select all

stopAllTimers()
{
	global timerArray
	
	for index, element in timerArray{
		element.Delete()	
	}
}
But even though timerArray.Length would show the correct number of Timers in the array, and the Delete function is being called, the timers never stop. Feels as if the references stored in the array are not the original objects but a copy, so the originals timers are still alive and kicking.

Full code here

The full code is still a very slimmed version of the original and there may be inconsistencies, but it should still show what my main problem is.
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Can't stop Timer object from instance

07 Jun 2019, 19:01

josemaloco wrote:
29 May 2019, 04:40
Hi josemaloco,

I'm not sure to fully understand what you're trying to implement. Here's a code more or less based on yours:

Code: Select all

#NoEnv
#SingleInstance force
#Warn
SendMode, Input


OnExit, handleExit
return
F1::new Timer(1000, Func("send").bind("1"))
F2::new Timer(2000, Func("send").bind("2"))
F3::
handleExit:
	Timer.deleteAll()
	if (A_ExitReason) ; if the subroutine has been caled as a result of the script being asked to terminate...
		ExitApp
return

send(varKey) {
	static _1 := 0
	static _2 := 0
	var := ++_%varKey%
	ToolTip % "{Numpad" . varKey . "}" . ++var, varKey * 100, 0, % varKey
}

Class Timer {
	static instances := [] ; keep track f instances by storing them directly in the base object
	__New(period, fn, params*) {
		this.fn := IsObject(fn) ? fn : Func(fn)
		this.params := params
		SetTimer % this, % period
	return this, Timer.instances.push(this)
	}
	Call() {
		local fn := this.fn
		%fn%(this.params*)
	}
	Delete() {
		SetTimer % this, Off
		SetTimer % this, Delete
		this.fn := "" ; remove the user-define object
	}
	DeleteAll() {
		local index, instance
		for index, instance in ObjClone(Timer.instances)
			instance.Delete(), Timer.instances.delete(index)
	}
}
Hope this helps.
my scripts
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Can't stop Timer object from instance  Topic is solved

08 Jun 2019, 03:52

But even though timerArray.Length would show the correct number of Timers in the array, and the Delete function is being called, the timers never stop.
this cant be true, look:

Code: Select all

beginMacro(macroFunction){
	global timerArray  := [] ; <<<<<
	...
u recreate the array every time u call the function, wiping out any timers that used to be stored in it
josemaloco
Posts: 2
Joined: 29 May 2019, 03:33

Re: Can't stop Timer object from instance

08 Jun 2019, 04:22

Unfortunately already ditched this approach, wiped my brain, and moved on. I though this thread would die, long forgotten.

Later on I found I had a problem with the way I was handling variables, because I was using this script within a collection of multiple scripts, and noticed too late my "header" script was wrong and was only putting in the autoexec zone some of
the global variables, which created a whole lot of strange behaviour all around with global variables not getting set. Most probably why I could retrieve the length of "timerArray" even though, as swagfag said, it should have reinitialized the array every time.

I ll mark swagfag answer as accepted as it is indeed a huge bug that would stop it from working. Thanks for checking it out!

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: filipemb, TAC109, wineguy and 304 guests