關於創建進度條的問題大家好。 我創建了一個帶有進度條和“取消”按鈕的窗口。 目的是允許用戶停止程序執行。 當我按取消時,我收到錯誤,並且不知道如何解決它。 我的腳本的簡化版本如下。
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
);如果我在循環運行時按“取消”,則會收到以下錯誤:
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);
) /*###*/;當按下取消按鈕時,我的期望是進度窗口應該關閉,然後執行應該停止。 但它似乎會繼續至少一次迭代,並在 For 循環中的 SB_L << Size() 行處失敗。 它失敗了,因為進度窗口已關閉並且 SB_L 已被刪除,但我很困惑為什麼如果發出 Stop() 命令則執行此行?
即使在我的 Stop() 命令之後程序執行仍在繼續,我是否正確? 按下“取消”按鈕後,如何防止執行 SB_L << Size() 命令?
細節:
JMP 專業版 15.2.1
Mac 操作系統 Big Sur v11.6
謝謝。
高級統計建模自動化和腳本編寫數據混合和清理大規模定制質量和工藝工程回复:關於創建進度條的問題不幸的是,如果不做本質上是不良做法的黑客行為,你就無法在這裡做你想做的事。JMP 腳本是單線程的,帶有取消按鈕的進度條大多只在多線程系統中有意義,在該系統中,主線程上有 GUI/事件循環,而工作線程上有所有腳本和函數調用。
即使在這些情況下,您也需要某種哨兵來正確處理取消等問題。當然可以使用取消按鈕殺死線程,但一般來說,您需要一個安全的停止路徑——某種中止分支。
您可以在 JSL 中執行此操作,但它需要等待( ... )陳述或<<更新窗口()聲明,兩者都可能產生嚴重後果。值得注意的是,您可能會在事件循環期間無意執行代碼,這些代碼可能會破壞腳本中的變量名稱 - 例如,如果圖形腳本存在於圖形上並被執行(JMP 非常積極地執行圖形腳本),則可能會發生這種情況,並且這些腳本可能來自您無法控制的其他插件存在於用戶系統上。當然,最好在腳本完成之前永遠不要將執行返回給事件循環(顯然要使腳本盡可能短,以避免 JMP 出現凍結)。簡而言之,不要將執行交還給事件循環。
我個人認為 JMP 團隊目前在 JSL 中沒有多線程執行範例(快到 2022 年了!)有點短視,但事實就是如此。
需要注意的一件事是——您可以運行外部程序並通過 IPC 通過 STDOUT 與它們對話。例如,您可以使用 Python 執行某種長時間運行的工作,並使用 STDOUT 來了解其何時完成(甚至可以在某種 STDOUT 哨兵上啟動 JMP 腳本)。
回复:關於創建進度條的問題是的。 按鈕腳本在其自己的“上下文”中運行;它不知道還有另一個腳本正在運行等待語句。 他們可以通過全局變量進行通信。 為了完成奇怪的可能性,在按鈕腳本中使用等待還意味著您可以單擊運行腳本的窗口上的關閉 X...當等待完成時, jmp 嘗試安全地停止腳本。 通常,如果在等待期間關閉了保存按鈕腳本的窗口,則等待後的下一條語句將不會被執行。
編輯:此外,需要等待來處理取消按鈕的點擊。
回复:關於創建進度條的問題嗨克雷格! 謝謝。 只是為了澄清,我添加的“等待(1)”只是為了模倣此演示的一組較長命令的執行,並給自己足夠的時間來單擊“取消”,以便我可以重現問題。 但並不打算讓等待成為腳本的必要部分。
如果我可以嘗試總結一下我相信你所說的話:
“取消”按鈕調用獨立於腳本 A(包含 For 循環的主腳本)的腳本 B。 腳本 B 中的 Stop 命令可以停止腳本 B 的執行,但不能/不會影響腳本 A。
我的說法正確嗎,更多/更少?
回复:關於創建進度條的問題wait( n ) 是 JMP 中不可避免的禍害,應盡可能避免。 在等待期間,調用 wait 的腳本會暫停,而操作系統可以執行一些操作,例如識別單擊或使打開的窗口可見。 奇怪的事情可能會發生,因為您可以使用單擊來啟動另一個接觸第一個腳本環境的腳本(您的示例)。 在您的示例中,stop() 正在停止第二個腳本。 它還可以設置全局標誌。 如果您的項目足夠大,需要擔心跟踪全局變量,您也可以使用名稱空間。
那麼可能發生什麼奇怪的事情呢? 大多數窗口被關閉,或者顯示框被刪除。 特別是,想像一下單擊函數有一個使用 wait(1) 的腳本,半秒後您再次單擊該按鈕。 該腳本的第二個副本正在第一個副本內運行。 原始的 wait(1) 在第二個腳本完成之前不會返回。 如果第二個腳本關閉按鈕所在的窗口,那麼原始腳本周圍的環境是什麼? (與等待之前不同!)不要構建沒有充分理由需要等待的腳本;大多數時候,displaybox<<回复:關於創建進度條的問題
剛剛注意到其他有趣的事情。 如果我在“取消”按鈕腳本中註釋掉“pwin << Close Window()”命令,則取消按鈕不再停止執行。 當從按鈕執行 Stop() 命令時,它似乎無法停止 For 循環。 取消按鈕之前之所以能夠停止執行,只是因為刪除窗口會產生錯誤。
回复:關於創建進度條的問題謝謝瑞安(和克雷奇)。 這是我肯定會考慮的一個選項,但它需要向主腳本正文中的 if 子句發送一個標誌。 我的願望是使用“取消”按鈕中的 Stop() 命令停止程序執行。 也許我可以重新構造我的問題:為什麼我的 Stop() 命令似乎沒有停止執行?
回复:關於創建進度條的問題你好@尼克爾斯。 您可能想查看最近的這篇文章@Craige_Hales ,帶有取消按鈕的進度條。