Pause Event Queue

If I send a whole slew of events to my application rapidy, it kind of goes nuts. I’d like to prevent it from doing that. Is there a way to temporarily halt new events from being processed until the previous event has been processed?

The above is my theory, anyway. What’s happening, specifically, occurs when I use the arrow keys to scroll in a table view. Each time the arrow key is hit, a new item is selected in the scroll view. When that happens, the ‘on selection changed’ event handler fires, and does quite a bit of work. It works perfectly if I hit the arrow key, pause a moment, then hit it again. But if I hold it down for a few seconds, then let go, I can see the selections changing as directed, but then all of a sudden it’ll start moving in the opposite direction. My theory is that my routine that updates the window is running several times in parallel, and the variables indicating where it is are getting updated more than once at a time. That’s the only thing I can think of that might be going on in my application to cause this. Does that make sense?

You could enable/disable the controls, or add something as this to your code:

--> pseudo-code

global codeRunning

set codeRunning to false

on clicked theButton
	if codeRunning then
		return
	else
		set codeRunning to true
		--> do whatever
		set codeRunning to false
	end if
end clicked

As I recall, Studio handles events on a last-in first-out basis. That means it receives a second event while handling the first, it’ll suspend its handling of the first event while it deals with the second, then resume handling the first when done. It’s a fundamentally dumb way of doing things since there’s nothing to stop these preemptive events stomping all over shared state (global variables, GUI widget settings) while others are using it, but it’s what you’re stuck with if you’re going to use Studio. Sane application frameworks handle incoming events on a first-in first-out basis, which is as it should be.

As jj says, you could disable the relevant controls or (assuming they’re not crucial) throw away any additional events during the time when you’re handling the original one. Another option is to move the time-consuming work out of the event handler and set up your own queue to drive that.

property _jobQueue : {}

on idle
	if _jobQueue is not {} then
		set jobDataRec to first item of _jobQueue
		set _jobQueue to rest of _jobQueue
		doJob(jobDataRec)
	end if
	return 1
end idle

on doJob(jobDataRec)
	-- time-consuming work done here
end doJob

on handled some event
	-- get data for job and stick it in a record or something
	set end of _jobQueue to jobDataRec
end handled some event

An uninformed thought — Could you use Jon’s Commands’ “keys pressed” to collect the key strokes and reverse the order of processing of a sequence? Doing so would make the app less responsive, of course, because there’d have to be some sort of timeout to see if another key command was coming. An approach like this would be useful if multiple commands were expected and a modifier key might signal that they were. At the end of the day, however, hhas is right; LIFO is a dumb default when FIFO is the norm and what you’d expect.