Can Applescript be multithreaded?

I am writing an Applescript for Spotify that is supposed to do two things:

  1. Log every new song played.
  2. Every N seconds check what sound device is used.

I do (1) by a simple loop that check how much of the track remains and then use that value in a delay statement in the loop (unnecessary to run the loop at full speed). However, N usually is much lower than the remaining time of the current track. Hence, I would like task (2) to run in a separate loop with N-0.5 as delay value. Basically I want to loops to run simultaneously from the same script. Is this possible?

(Of course I could use two separate scripts but I need to distribute this solution when it is done, therefore less visual complexity - i.e., two scripts running simultaneously taking up space in Dock, needing to be launched etc - is better.)


Not easily. The concept of processes and threads isn't contained in AppleScript.

You'll want another tool for that job. Swift might be a good one unless you're looking for python or something a bit more established.


Language Limits

As of macOS 10.13, AppleScript does not trivially support multithreading within a single script. It appears possible to use NSThread within an AppleScript but this is complex and leads to a second limitation, that of the application being interacted with.

Application Limits

In addition to the AppleScript language itself not natively representing threads, the called application is unlikely to deal with AppleEvents in a thread optimal manner. AppleEvents are queued by macOS in a First-In First-Out (FIFO) order for processing by the application.

The application can defer responses to long running AppleEvents but this requires additional engineering that few applications implement. Most applications will block until the AppleEvent is processed before looking at the next AppleEvent.

This means a multi-threaded AppleScript talking to single application would likely not see the performance gains expected for the effort.

Single Event Loop?

You could approach the problem with a single loop dealing with multiple events. The single loop could sleep for N seconds, wake and deal with the pending appropriate tasks.

Piyomaru's answer shows one way to implement an event based approach. This approach is not multi-threaded or parallel; it is an event driven loop.


AppleScript now supports multi-threading (macOS 10.10 or later). And originally it has timer interrupt function since 1993 (on idle timer event handler works concurrently within single AppleScript).

I wrote some AppleScripts with iTunes like you wrote. AppleScript can make delegates and receive other application's event.

This sample AppleScript can receive iTunes's playing state change. Once, the script run on Script Editor, it receive the change event of iTunes playing and displays name of track using macOS notification dialog.

-- Created 2017-10-13 by Takaaki Naganoya
-- 2017 Piyomaru Software

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSDistributedNotificationCenter : a reference to current application's NSDistributedNotificationCenter

on run
    NSDistributedNotificationCenter's defaultCenter()'s addObserver:me selector:"statusChanged:" |name|:"com.apple.iTunes.playerInfo" object:(missing value)

end run

on statusChanged:sender
    tell application id "com.apple.iTunes"
        try
            tell current track
                set anAlbum to album
                set aName to name
                set anArtist to album artist
                set aRating to rating
            end tell
        on error
            return
        end try
    end tell
    display notification aName
end statusChanged:

So, the point is Spotify application can provide such a function like iTunes or not.