Domanda sulla creazione di barre di avanzamentoCiao a tutti. Ho creato una finestra con una barra di avanzamento e un pulsante "Annulla". L'intento è quello di consentire all'utente di interrompere l'esecuzione del programma. Ricevo un errore quando premo Annulla e non so come risolverlo. Di seguito è riportata una versione semplificata del mio script.
Names Default to Here(1);
//Define progress window
pwin = NewWindow("Progress",
SB_L = SpacerBox(Size(0, 15), Color("Green")),
ButtonBox("Cancel",
pwin << Close Window;
Stop();
)
);
//Sample Loop
For(i=1, i<=10, i++,
SB_L << Size(i*10, 15); //update the progress bar
Wait(1); //rest of loop
);Se premo Annulla mentre il ciclo è in esecuzione, ottengo il seguente errore:
deleted object reference: SB_L << Size(i * 10, 15) in access or evaluation of 'Glue' , pwin = New Window("Progress",
SB_L = Spacer Box(Size(0, 15), Color("Green")),
Button Box("Cancel",
pwin << Close Window;
Stop();
)
); /*###*/For(i = 1, i <= 10, i++,
SB_L << Size(i * 10, 15);
Wait(1);
) /*###*/;Quando viene premuto il pulsante Annulla, la mia aspettativa è che la finestra di avanzamento si chiuda e quindi l'esecuzione si interrompa. Ma sembra continuare per almeno un'iterazione e fallisce nella riga SB_L << Size() nel ciclo For. Fallisce perché la finestra di avanzamento si è chiusa e SB_L è stato eliminato, ma sono confuso perché questa riga viene eseguita se è stato emesso il comando Stop()?
Ho ragione che l'esecuzione del programma continua anche dopo il mio comando Stop()? Come posso impedire l'esecuzione del comando SB_L << Size() dopo che è stato premuto il pulsante Annulla?
Dettagli:
JMP Pro 15.2.1
Mac OS BigSur v11.6
Grazie.
Modellazione statistica avanzataAutomazione e scriptingMiscelazione e pulizia dei datiPersonalizzazione di massaQualità e ingegneria di processoRi: Domanda sulla creazione di barre di avanzamentoSfortunatamente non puoi fare quello che vuoi qui senza fare quello che è essenzialmente un hack di cattiva pratica.Gli script JMP sono a thread singolo e una barra di avanzamento con un pulsante di annullamento ha senso solo in un sistema multi-thread in cui hai la GUI/Event Loop sul thread principale e tutti gli script e le chiamate di funzione sui thread di lavoro.
Anche in questi casi, però, avresti bisogno di una sorta di sentinella per gestire correttamente gli annullamenti e simili.Sarebbe certamente possibile avere un pulsante di annullamento che uccida i thread, ma in generale è necessario un percorso di arresto sicuro, una sorta di ramo di interruzione.
Puoi farlo in JSL, ma richiede entrambi Aspettare( ... ) dichiarazioni o <<AGGIORNA finestra=""> affermazioni, entrambe con conseguenze potenzialmente gravi.In particolare, è possibile avere codice che viene eseguito involontariamente durante il ciclo di eventi che può alterare i nomi delle variabili all'interno dello script: ciò può accadere, ad esempio, se uno script grafico esiste su un grafico e viene eseguito (JMP esegue in modo estremamente aggressivo gli script grafici) e questi script possono esistere su un sistema utente da altri componenti aggiuntivi al di fuori del proprio controllo.È sicuramente meglio non restituire mai l'esecuzione all'Event Loop finché lo script non è terminato (e ovviamente mantenere lo script il più breve possibile per evitare che JMP appaia bloccato).Lungo e breve è: non restituire l'esecuzione al ciclo di eventi.</AGGIORNA>
Personalmente trovo un po' miope da parte del team JMP non avere un paradigma di esecuzione multi-thread all'interno di JSL a questo punto (è quasi il 2022!), ma è quello che è.
Una cosa da notare: puoi eseguire programmi esterni e parlare con loro tramite IPC tramite STDOUT.Puoi, ad esempio, utilizzare Python per eseguire una sorta di lavoro di lunga durata e utilizzare STDOUT per sapere quando è finito (e persino avviare uno script JMP su una sorta di sentinella STDOUT).
Ri: Domanda sulla creazione di barre di avanzamentoSÌ. Lo script del pulsante viene eseguito nel proprio "contesto"; non ha idea che ci sia un altro script che esegue un'istruzione wait. Possono comunicare tramite globals. E per finire le strane possibilità, usare un'attesa in uno script di pulsanti significa anche che puoi fare clic sulla X di chiusura nella finestra che esegue lo script ... quando l'attesa finisce, jmp tenta di interrompere lo script in modo sicuro. Di solito l'istruzione successiva dopo l'attesa non verrà eseguita se la finestra che contiene lo script del pulsante viene chiusa durante l'attesa.
Modifica: inoltre, l'attesa è necessaria per elaborare il clic sul pulsante Annulla.
Ri: Domanda sulla creazione di barre di avanzamentoCiao Craig! Grazie. Giusto per chiarire, "Wait(1)" che ho aggiunto era solo per simulare l'esecuzione di un insieme più lungo di comandi per questa demo e per darmi abbastanza tempo per fare clic su "Annulla" in modo da poter riprodurre il problema. Tuttavia, non intendevo che l'attesa fosse una parte necessaria della sceneggiatura.
Se potessi tentare di riassumere quello che credo tu stia dicendo:
Il pulsante Annulla chiama lo script B che è indipendente dallo script A (lo script principale che contiene il ciclo For). Il comando Stop nello script B è in grado di interrompere l'esecuzione dello script B, ma non può/non influenzerà lo script A.
Ho corretto, più/meno?
Ri: Domanda sulla creazione di barre di avanzamentowait( n ) è un male necessario in JMP, da evitare ove possibile. Durante un'attesa, lo script che chiama wait viene messo in pausa mentre il sistema operativo può eseguire operazioni, come riconoscere un clic o rendere visibile una finestra aperta. Possono accadere cose strane, perché puoi usare il clic per avviare un altro script (il tuo esempio) che tocca l'ambiente del primo script. Nel tuo esempio, stop() interrompe il secondo script. Può anche impostare un flag globale. Se il tuo progetto è abbastanza grande da preoccuparti di tenere traccia delle variabili globali, puoi anche utilizzare gli spazi dei nomi.
Quindi qual è la cosa strana che può succedere? Per lo più finestre chiuse o finestre di visualizzazione eliminate. In particolare, immagina una funzione click che ha uno script che utilizza wait(1) e fai di nuovo clic sul pulsante, mezzo secondo dopo. Una seconda copia dello script è in esecuzione all'interno della prima. L'originale wait(1) non tornerà fino al termine del secondo script. Se il secondo script chiude la finestra in cui risiede il pulsante, quale ambiente si trova intorno allo script originale? (non lo stesso di prima dell'attesa!) Non creare script che richiedono l'attesa senza una buona ragione; la maggior parte delle volte displaybox<<
Ri: Domanda sulla creazione di barre di avanzamentoHo appena notato qualcos'altro di interessante. Se commento il comando "pwin << Close Window()" nello script del pulsante Annulla, il pulsante Annulla non interrompe più l'esecuzione. Sembra che il comando Stop() non sia in grado di fermare il ciclo For quando viene eseguito da un pulsante. Il pulsante Annulla è stato in grado di interrompere l'esecuzione prima solo perché la rimozione della finestra ha creato un errore.
Ri: Domanda sulla creazione di barre di avanzamentoGrazie Ryan (e Craige). Questa è stata un'opzione che sto decisamente prendendo in considerazione, ma richiede l'invio di un flag a una clausola if nel corpo dello script principale. Il mio desiderio è semplicemente interrompere l'esecuzione del programma utilizzando il comando Stop() nel pulsante Annulla. Forse posso riformulare la mia domanda: perché il mio comando Stop() non sembra interrompere l'esecuzione?
Ri: Domanda sulla creazione di barre di avanzamentoCIAO @nikles . Potresti voler dare un'occhiata a questo recente post di @Craige_Hales , Barra di avanzamento con pulsante Annulla .