Question sur la création de barres de progressionSalut tout le monde. J'ai créé une fenêtre avec une barre de progression et un bouton "Annuler". L'intention est de permettre à l'utilisateur d'arrêter l'exécution du programme. Cependant, j'obtiens une erreur lorsque j'appuie sur Annuler et je ne sais pas comment la résoudre. Une version simplifiée de mon script est ci-dessous.
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
);Si j'appuie sur Annuler pendant que la boucle est en cours d'exécution, j'obtiens l'erreur suivante :
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);
) /*###*/;Lorsque le bouton d'annulation est enfoncé, je m'attends à ce que la fenêtre de progression se ferme, puis l'exécution s'arrête. Mais il semble continuer pendant au moins une itération et échoue à la ligne SB_L << Size() dans la boucle For. Cela échoue car la fenêtre de progression s'est fermée et SB_L a été supprimé, mais je ne comprends pas pourquoi cette ligne est exécutée si la commande Stop() a été émise ?
Ai-je raison de dire que l'exécution du programme se poursuit même après ma commande Stop() ? Comment puis-je empêcher l'exécution de la commande SB_L << Size() après avoir appuyé sur le bouton Annuler ?
Détails:
JMP Pro 15.2.1
Mac OS Big Sur v11.6
Merci.
Modélisation statistique avancéeAutomatisation et scriptFusion et nettoyage des donnéesPersonnalisation de masseIngénierie de la qualité et des procédésRe : Question sur la création de barres de progressionMalheureusement, vous ne pouvez pas faire ce que vous voulez ici sans faire ce qui est essentiellement un hack de mauvaise pratique.Les scripts JMP sont à thread unique et une barre de progression avec un bouton d'annulation n'a généralement de sens que dans un système multithread où vous avez l'interface graphique/la boucle d'événement sur le thread principal et tous les scripts et appels de fonction sur les threads de travail.
Même dans ces cas, vous auriez besoin d'une sorte de sentinelle pour gérer correctement les annulations et autres.Il serait certainement possible d'avoir un bouton d'annulation pour tuer les threads, mais en général, vous avez besoin d'un chemin d'arrêt sûr - une sorte de branche d'abandon.
Vous pouvez le faire en JSL, mais cela nécessite soit Attendez( ... ) déclarations ou <<FENÊTRE de="" mise="" à="" jour=""> déclarations, qui ont toutes deux des conséquences potentiellement graves.Notamment, vous pouvez avoir du code exécuté involontairement pendant la boucle d'événements qui peut modifier les noms de variables dans votre script -- cela peut se produire, par exemple, si un script graphique existe sur un graphique et est exécuté (JMP exécute de manière extrêmement agressive des scripts graphiques), et ces scripts peuvent exister sur un système utilisateur à partir d'autres compléments indépendants de votre volonté.Il est certainement préférable de ne jamais redonner l'exécution à la boucle d'événements tant que votre script n'est pas terminé (et évidemment de garder le script aussi court que possible pour éviter que JMP apparaisse figé).En bref, ne redonnez pas l'exécution à la boucle d'événements.</FENÊTRE>
Personnellement, je trouve un peu myope de la part de l'équipe JMP de ne pas avoir de paradigme d'exécution multithread au sein de JSL à ce stade (c'est presque 2022 !), mais c'est ce que c'est.
Une chose à noter - vous pouvez exécuter des programmes externes et leur parler via IPC via STDOUT.Vous pouvez, par exemple, utiliser Python pour effectuer une sorte de travail de longue durée et utiliser STDOUT pour savoir quand il est terminé (et même démarrer un script JMP sur une sorte de sentinelle STDOUT).
Re : Question sur la création de barres de progressionOui. Le script du bouton s'exécute dans son propre "contexte" ; il n'a aucune idée qu'il existe un autre script exécutant une instruction d'attente. Ils peuvent communiquer via des globals. Et pour finir les possibilités étranges, utiliser une attente dans un script de bouton signifie également que vous pouvez cliquer sur le X de fermeture sur la fenêtre exécutant le script... lorsque l'attente se termine, jmp essaie d'arrêter le script en toute sécurité. Habituellement, la prochaine instruction après l'attente ne sera pas exécutée si la fenêtre contenant le script du bouton est fermée pendant l'attente.
Edit : aussi, l'attente est nécessaire pour traiter le clic sur le bouton d'annulation.
Re : Question sur la création de barres de progressionSalut Craig! Merci. Juste pour clarifier, le "Wait (1)" que j'ai ajouté n'était que pour imiter l'exécution d'un ensemble de commandes plus long pour cette démo, et pour me donner suffisamment de temps pour cliquer sur "Annuler" afin que je puisse reproduire le problème. Cependant, l'attente n'était pas destinée à être une partie nécessaire du script.
Si je pouvais essayer de résumer ce que je crois que vous dites:
Le bouton Annuler appelle le script B qui est indépendant du script A (le script principal contenant la boucle For). La commande Stop dans le script B est capable d'arrêter l'exécution du script B, mais ne peut pas/n'affectera pas le script A.
Ai-je raison, plus/moins ?
Re : Question sur la création de barres de progressionwait( n ) est un mal nécessaire dans JMP, à éviter dans la mesure du possible. Pendant une attente, le script qui appelle l'attente est mis en pause pendant que le système d'exploitation peut faire des choses, comme reconnaître un clic ou rendre visible une fenêtre ouverte. Des choses étranges peuvent arriver, car vous pouvez utiliser le clic pour démarrer un autre script (votre exemple) qui touche l'environnement du premier script. Dans votre exemple, stop() arrête le deuxième script. Il peut également définir un indicateur global. Si votre projet est suffisamment important pour vous soucier du suivi des variables globales, vous pouvez également utiliser des espaces de noms.
Alors, quelle est la chose étrange qui peut arriver? Principalement des fenêtres fermées ou des boîtes d'affichage supprimées. En particulier, imaginez une fonction de clic qui a un script qui utilise wait(1), et vous cliquez à nouveau sur le bouton, une demi-seconde plus tard. Une deuxième copie du script s'exécute à l'intérieur de la première. Le wait(1) d'origine ne reviendra qu'une fois le deuxième script terminé. Si le deuxième script ferme la fenêtre dans laquelle se trouve le bouton, quel environnement entoure le script d'origine ? (pas le même qu'avant l'attente !) Ne construisez pas de scripts nécessitant une attente sans une bonne raison ; la plupart du temps displaybox<<
Re : Question sur la création de barres de progressionJe viens de remarquer autre chose d'intéressant. Si je commente la commande "pwin << Fermer la fenêtre ()" dans le script du bouton Annuler, le bouton Annuler n'arrête plus l'exécution. Il semble que la commande Stop() ne soit pas capable d'arrêter la boucle For lorsqu'elle est exécutée à partir d'un bouton. Le bouton Annuler a pu arrêter l'exécution auparavant uniquement parce que la suppression de la fenêtre a créé une erreur.
Re : Question sur la création de barres de progressionMerci Ryan (et Craige). C'était une option que j'envisageais certainement, mais elle nécessite l'envoi d'un indicateur à une clause if dans le corps du script principal. Mon souhait est simplement d'arrêter l'exécution du programme en utilisant la commande Stop () dans le bouton Annuler. Peut-être puis-je reformuler ma question : pourquoi ma commande Stop() ne semble-t-elle pas arrêter l'exécution ?
Re : Question sur la création de barres de progressionSalut @nikles . Vous voudrez peut-être consulter ce message récent de @Craige_Hales , Barre de progression avec bouton Annuler .