two idle loops at different intervals

I’m trying to get to run two idle loops at different intervals. The following illustrative code works to some extent but there is a noticeable lag between loops.

Is there a better way for this without the lag between loops? Maybe using a different approach alltogether?

property Delay1 : 1
property Delay2 : 10

on idle
	set i to 0
	repeat until i is greater than (Delay2 - Delay1)
		-- do something, for example
		beep
		set i to i + Delay1
		delay Delay1
	end repeat
	-- do something else, for example
	say "Beep"
	return
end idle

What do you wish to accomplish?

I want to monitor motion with AMStracker at short intervals (less than a second) and monitor the SSID at long intervals (about a minute). If motion is detected an alarm sound will go off and if the SSID changes the script will log off. As the user can set which to monitor I need to set loops for both. The current lag between loops is around 15-20 seconds and is too long since during this period motion cannot be detected.

I found a working way but unfortunately it’s not using the on idle call:

property Delay1 : 1
property Delay2 : 10

repeat
	set i to 0
	repeat until i is greater than (Delay2 - Delay1)
		beep
		delay Delay1
		set i to i + Delay1
		if i is Delay2 then
			say "beep"
		end if
	end repeat
end repeat

This script isn’t using an idle as it’s intended. An “on idle” handler expects a “return n” statement where n is the number of seconds to the next cycle measured from that point (meaning that the total cycle time is the run time + idle setting). To run at two different rates that are an integer multiple of each other should be accomplished with a count of the short cycle time.


set c to 0

on idle
	set c to c + 1
	
	-- do your short cycle thing
	
	if c is 10 then
		
		-- do the long cycle thing
		set c to 0
		
	end if
	
	return 1
end idle

There are many roads to Rome, but some are far better than the others. Thank you!!! This works perfectly and much much better than what I had before.

Hi, Stadsman.

I see Adam’s beaten me to the post, but to complement what he’s written:

An ‘idle’ handler is used in a stay-open script applet. If it doesn’t return a value at the end (as in your first script), or if it returns 0 or something that can’t be interpreted as a positive number, the system calls it every 30 seconds. That’s why you were getting the delay between the loops. The handler needs to return a value which tells the system how many seconds to wait before calling it again.

property Delay1 : 1
property Delay2 : 10

global i
set i to 0

on idle
	-- do something, for example
	beep
	set i to i + Delay1
	if (i ≥ Delay2) then
		-- do something else, for example
		say "Beep"
		set i to 0
	end if
	
	return Delay1
end idle

Returning a value every time, as above, resets the idle interval each time and the next call is made Delay1 seconds after the handler finishes. A slightly different approach would be to set the idle interval on the first idle only. After that, it would remain unchanged and the system would poll the handler regularly every Delay1 seconds (instead of Delay1 seconds after the handler finishes).

property Delay1 : 1
property Delay2 : 10

global i, firstRun
set i to 0
set firstRun to true

on idle
	-- do something, for example
	beep
	set i to i + Delay1
	if (i ≥ Delay2) then
		-- do something else, for example
		say "Beep"
		set i to 0
	end if
	
	if (firstRun) then
		set firstRun to false
		return Delay1
	end if
end idle

If the handler’s still doing something when it’s called again, the call simply goes unheeded.

In the scripts above, Delay2 is based on Delay1 rather than the actual interval that takes place, so it may get out slightly. It sounds as if that might not matter very much for your purposes. For greater precision, it would be better to have two stay-open applets, each with its own idle interval.

Excellent explanation, it really made me understand the idle handler much better. Thanks for the tow of you!