Pregunta sobre la creación de barras de progresoHola a todos. Creé una ventana con una barra de progreso y un botón "Cancelar". La intención es permitir que el usuario detenga la ejecución del programa. Sin embargo, recibo un error cuando presiono cancelar y no sé cómo resolverlo. A continuación se muestra una versión simplificada de mi 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
);Si presiono Cancelar mientras se ejecuta el bucle, aparece el siguiente error:
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);
) /*###*/;Cuando se presiona el botón cancelar, mi expectativa es que la ventana de progreso se cierre y luego la ejecución se detenga. Pero parece continuar durante al menos una iteración y falla en la línea SB_L << Size() en el ciclo For. Falla porque la ventana de progreso se cerró y se eliminó SB_L, pero estoy confundido por qué se ejecuta esta línea si se emitió el comando Stop().
¿Tengo razón en que la ejecución del programa continúa incluso después de mi comando Stop()? ¿Cómo puedo evitar la ejecución del comando SB_L << Size() después de presionar el botón Cancelar?
Detalles:
JMP Pro 15.2.1
Mac OS Big Sur v11.6
Gracias.
Modelado Estadístico AvanzadoAutomatización y secuencias de comandosFusión y limpieza de datosLa personalización en masaIngeniería de Calidad y ProcesosRe: Pregunta sobre la creación de barras de progresoDesafortunadamente, no puedes hacer lo que quieras aquí sin hacer lo que es esencialmente un truco de mala práctica.Los scripts JMP son de un solo subproceso, y una barra de progreso con un botón de cancelación en su mayoría solo tiene sentido en un sistema de subprocesos múltiples donde tiene la GUI / Event Loop en el subproceso principal y todos los scripts y llamadas de función en subprocesos de trabajo.
Incluso en estos casos, necesitaría algún tipo de centinela para manejar adecuadamente las cancelaciones y demás.Ciertamente, sería posible tener un botón de cancelación que elimine los subprocesos, pero en general necesita una ruta de parada segura, algún tipo de rama de cancelación.
Puede hacer esto en JSL, pero requiere ya sea Esperar( ... ) declaraciones o <<ACTUALIZAR ventana=""> declaraciones, las cuales tienen consecuencias potencialmente graves.En particular, puede tener un código que se ejecuta involuntariamente durante el bucle de eventos que puede alterar los nombres de las variables dentro de su secuencia de comandos; esto puede suceder, por ejemplo, si existe una secuencia de comandos de gráficos en un gráfico y se ejecuta (JMP ejecuta secuencias de comandos de gráficos de manera extremadamente agresiva), y estas secuencias de comandos pueden existir en un sistema de usuarios desde otros complementos fuera de su control.Sin duda, es mejor nunca devolver la ejecución al Event Loop hasta que su secuencia de comandos haya terminado (y, obviamente, mantener la secuencia de comandos lo más corta posible para evitar que JMP parezca congelado).En resumidas cuentas, no devuelva la ejecución al bucle de eventos.</ACTUALIZAR>
Personalmente, me parece un poco miope por parte del equipo de JMP no tener un paradigma de ejecución de subprocesos múltiples dentro de JSL en este momento (¡es casi 2022!), Pero es lo que es.
Una cosa a tener en cuenta: puede ejecutar programas externos y hablar con ellos a través de IPC a través de STDOUT.Puede, por ejemplo, usar Python para hacer algún tipo de trabajo de larga duración y usar STDOUT para saber cuándo ha terminado (e incluso iniciar un script JMP en algún tipo de centinela STDOUT).
Re: Pregunta sobre la creación de barras de progresoSí. El script del botón se ejecuta en su propio "contexto"; no tiene idea de que hay otra secuencia de comandos que ejecuta una declaración de espera. Pueden comunicarse a través de globales. Y para finalizar las extrañas posibilidades, usar una espera en un script de botón también significa que puede hacer clic en la X de cerrar en la ventana que ejecuta el script... cuando finaliza la espera, jmp intenta detener el script de forma segura. Por lo general, la siguiente declaración después de la espera no se ejecutará si la ventana que contiene el script del botón se cierra durante la espera.
Editar: también, se necesita esperar para procesar el clic en el botón cancelar.
Re: Pregunta sobre la creación de barras de progreso¡Hola Craige! Gracias. Solo para aclarar, el "Esperar (1)" que agregué fue solo para imitar la ejecución de un conjunto más largo de comandos para esta demostración y para darme tiempo suficiente para hacer clic en "Cancelar" para poder reproducir el problema. Sin embargo, no tenía la intención de que Wait fuera una parte necesaria del guión.
Si pudiera intentar resumir lo que creo que estás diciendo:
El botón Cancelar llama a la secuencia de comandos B que es independiente de la secuencia de comandos A (la secuencia de comandos principal que contiene el bucle For). El comando Detener en el script B puede detener la ejecución del script B, pero no puede/no afectará al script A.
¿Tengo eso correcto, más/menos?
Re: Pregunta sobre la creación de barras de progresowait(n) es un mal necesario en JMP, que debe evitarse en la medida de lo posible. Durante una espera, la secuencia de comandos que llama a la espera se detiene mientras el sistema operativo puede hacer cosas, como reconocer un clic o hacer visible una ventana abierta. Pueden suceder cosas extrañas, porque puede usar el clic para iniciar otro script (su ejemplo) que toca el entorno del primer script. En su ejemplo, stop() detiene el segundo script. También puede establecer una bandera global. Si su proyecto es lo suficientemente grande como para preocuparse por realizar un seguimiento de las variables globales, también puede usar espacios de nombres.
Entonces, ¿qué es lo raro que puede pasar? La mayoría de las veces se cierran ventanas o se eliminan cuadros de visualización. En particular, imagina una función de clic que tiene un script que usa esperar (1), y vuelves a hacer clic en el botón, medio segundo después. Una segunda copia del script se está ejecutando dentro de la primera. El wait(1) original no volverá hasta que finalice el segundo script. Si la segunda secuencia de comandos cierra la ventana en la que se encuentra el botón, ¿qué entorno rodea a la secuencia de comandos original? (¡No es el mismo que antes de la espera!) No cree scripts que requieran una espera sin una buena razón; la mayoría de las veces displaybox<<
Re: Pregunta sobre la creación de barras de progresoAcabo de notar algo más interesante. Si comento el comando "pwin << Cerrar ventana ()" en el script del botón Cancelar, el botón cancelar ya no detiene la ejecución. Parece que el comando Stop() no puede detener For Loop cuando se ejecuta desde un botón. El botón Cancelar pudo detener la ejecución antes solo porque la eliminación de la ventana generó un error.
Re: Pregunta sobre la creación de barras de progresoGracias Ryan (y Craige). Esta fue una opción que definitivamente estoy considerando, pero requiere enviar un indicador a una cláusula if en el cuerpo principal del script. Mi deseo es simplemente detener la ejecución del programa usando el comando Stop() en el botón Cancelar. Tal vez pueda reformular mi pregunta: ¿por qué mi comando Stop() no parece detener la ejecución?
Re: Pregunta sobre la creación de barras de progresoHola @nikles . Es posible que desee consultar esta publicación reciente de @Craige_Hales , Barra de progreso con botón Cancelar .