[Posting this on the normal AppleScript forum, as I think the discussion is not strictly ASS-related.]
I’ve got an AppleScript Studio application which I’m doing some maintenance on; unfortunately I need to retain compatibility with Mac OS X 10.6, so moving to ASOC is not an option.
My app is working generally well; it does a lot of looping actions, so I present a progress bar and label showing the current item being operated on in the UI. However, the progress bar and label don’t accurately match the state of the app - they get somewhat sluggish and left behind, even though the actual processing is proceeding as expected.
I presume that I’m falling foul of AppleScript’s single-threaded model here, and that I should look to move the ‘do work’ code off the main thread and onto a background thread, along the lines of discussion here: http://www.macscripter.net/viewtopic.php?id=34563 - thanks Bastiaan!
However, I can’t see how to get variables from the background thread back into the main thread, in order to update the UI elements.
The options I’ve thought of are:
Call a function in the main thread from the background thread, passing the variables as arguments. How would I address the main thread function from the background thread? And does this just move the blockage from the main thread to the background thread?
Update a global variable from the background thread. But I can’t find the equivalent of a ‘didChange’ notification, on which to trigger a UI update function in the main thread;
Update a global variable from the background thread, and have the main thread update the UI on a loop with a delay - but then the UI isn’t really much more responsive than in the original case!
You’re welcome :). Nice to tho see that post is still useful to some people.
There are properties of the UI element of the applications that can be shared, don’t forget that AS-Studio applications are fully scriptable. Instead of sharing a variable you can put the variable content into the one of the UI element properties or just create an hidden UI element. I know it’s not the most beautiful solution but it works and in user land you don’t notice it at all. I remember using an hidden window with UI elements to share data between the app and external scripts. You can even trigger events with hidden buttons that are clicked by the background application.
It’s been an long time but IIRC you need something like this:
--In the background application
Tell application "My AS-Studio appliciation"
tell window "share"
tell button "shared data 1"
set title to "some data"
-- in your application
on clicked theObject
if name of theObject is "Shared data 1"
set theContents to title of theObject
end on clicked
I was successfully able to follow Bastiaan’s suggestion to pass a variable back to the main application from the background application by entering it into a text field - but I then encountered a couple of other problems:
(1) (Unless I’m mistaken) I’d forgotten that you need to enable access for assistive devices to allow AppleScript to click the button of another application - and this is something I want to avoid. I deploy my application across quite a wide user base, and I don’t want them to have to go through this step to do it. So I can’t use Bastiaan’s suggestion to provide an update notification path;
(2) I consequently put the UI updating code in the main application into an idle handler - but I found that this was only calling at a maximum rate of about once per second - and I ideally wanted my UI to update more frequently than that.
So I’ve decided to keep my processing code inside the main application - but have found that by adding a ‘delay 0.01’ statement in my repeat loop, immediately after the UI update code, my UI is now super-super-responsive!
Hope this is helpful to anyone else still writing code back in the dark ages…