Can Applescript può essere multithreaded?

7

Sto scrivendo un Applescript per Spotify che dovrebbe fare due cose:

  1. Registra ogni nuovo brano riprodotto.
  2. Ogni N secondi controlla quale dispositivo audio viene utilizzato.

Faccio (1) da un semplice ciclo che controlla quanta parte della traccia rimane e poi usa quel valore in un'istruzione delay nel loop (non è necessario eseguire il loop a tutta velocità). Tuttavia, N di solito è molto più basso del tempo rimanente della traccia corrente. Quindi, vorrei task (2) per eseguire in un ciclo separato con N-0.5 come valore di ritardo. Fondamentalmente voglio loop per eseguire contemporaneamente dallo stesso script. È possibile?

(Naturalmente potrei usare due script separati ma ho bisogno di distribuire questa soluzione quando è terminata, quindi meno complessità visiva - cioè, due script che funzionano simultaneamente occupando spazio nel Dock, che devono essere lanciati ecc. - è meglio. )

    
posta d-b 03.10.2017 - 13:55
fonte

4 risposte

2

Non facilmente. Il concetto di processi e thread non è contenuto in AppleScript.

Avrai bisogno di un altro strumento per quel lavoro. Swift potrebbe essere buono a meno che tu non stia cercando Python o qualcosa di più consolidato.

    
risposta data 03.10.2017 - 14:01
fonte
2

Limiti di lingua

A partire da macOS 10.13, AppleScript non supporta banalmente il multithreading all'interno di un singolo script. Sembra possibile utilizzare NSThread all'interno di un AppleScript, ma questo è complesso e porta a una seconda limitazione, quella dell'interazione con l'applicazione.

Limiti dell'applicazione

Oltre al linguaggio AppleScript stesso che non rappresenta in modo nativo i thread, è improbabile che l'applicazione chiamata gestisca AppleEvents in un thread ottimizzato. AppleEvents viene accodato da macOS in un ordine FIFO (First-In First-Out) per l'elaborazione da parte dell'applicazione.

L'applicazione può rinviare le risposte a AppleEvents a lungo in esecuzione, ma ciò richiede un'ingegneria aggiuntiva implementata da poche applicazioni. La maggior parte delle applicazioni bloccherà fino a quando AppleEvent verrà elaborato prima di esaminare il prossimo AppleEvent.

Questo significa che un AppleScript multi-threading che parla con una singola applicazione probabilmente non vedrà i guadagni prestazionali attesi per lo sforzo.

Ciclo evento singolo?

Potresti affrontare il problema con un singolo ciclo che si occupa di più eventi. Il loop singolo potrebbe dormire per N secondi, svegliarsi e gestire le attività appropriate in sospeso.

La risposta di Piyomaru mostra un modo per implementare un approccio basato sugli eventi. Questo approccio non è multi-thread o parallelo; è un ciclo guidato da eventi.

    
risposta data 03.10.2017 - 14:02
fonte
1

AppleScript adesso supporta il multi-threading (macOS 10.10 o successivo ). E originariamente ha una funzione di interruzione del timer dal 1993 (il gestore di eventi del timer on idle funziona contemporaneamente all'interno di un singolo AppleScript).

Ho scritto alcuni AppleScript con iTunes come hai scritto tu. AppleScript può creare delegati e ricevere l'evento di altre applicazioni.

Questo AppleScript di esempio può ricevere la modifica dello stato di riproduzione di iTunes. Una volta, lo script viene eseguito su Script Editor, riceve l'evento di modifica della riproduzione di iTunes e visualizza il nome della traccia utilizzando la finestra di dialogo di notifica di macOS.

-- 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:

Quindi, il punto è che l'applicazione Spotify può fornire una funzione come iTunes o meno.

    
risposta data 13.10.2017 - 08:45
fonte
0

Suggerirei di scrivere questo in JavaScript piuttosto che in AppleScript. JavaScript è una lingua supportata per lo scripting di eventi Apple. JavaScript è a thread singolo, ma è molto più semplice scrivere codice asincrono non bloccante.

setInterval(function() {
    console.log('Do something in the closure function here');
}, 3000);
    
risposta data 03.10.2017 - 18:28
fonte

Leggi altre domande sui tag