プログレスバーの作成に関する質問こんにちは、みんな。 進行状況バーと「キャンセル」ボタンを含むウィンドウを作成しました。 その目的は、ユーザーがプログラムの実行を停止できるようにすることです。 キャンセルを押すとエラーが発生するのですが、解決方法がわかりません。 私のスクリプトの簡略版を以下に示します。
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);
) /*###*/;キャンセル ボタンが押されると、進行状況ウィンドウが閉じて、実行が停止するはずです。 しかし、少なくとも 1 回の反復は継続しているように見え、For ループの SB_L << Size() 行で失敗します。 進行状況ウィンドウが閉じられ、SB_L が削除されたために失敗しますが、Stop() コマンドが発行されたのになぜこの行が実行されるのか混乱しています。
Stop() コマンドの後でもプログラムの実行は継続しているということでよろしいでしょうか? 「キャンセル」ボタンが押された後に SB_L << Size() コマンドが実行されないようにするにはどうすればよいですか?
詳細:
JMP プロ 15.2.1
Mac OS Big Sur v11.6
ありがとう。
高度な統計モデリング自動化とスクリプト作成データのブレンディングとクリーンアップマスカスタマイゼーション品質およびプロセスエンジニアリングRe: プログレスバーの作成に関する質問残念ながら、基本的に悪い習慣のハックを行わずに、ここでやりたいことを行うことはできません。JMP スクリプトはシングル スレッドであり、キャンセル ボタンのあるプログレス バーは、メイン スレッドに GUI / イベント ループがあり、ワーカー スレッドにすべてのスクリプトと関数呼び出しがあるマルチスレッド システムでのみ意味を持ちます。
ただし、このような場合でも、キャンセルなどを適切に処理するには、ある種の監視員が必要になります。確かにキャンセル ボタンでスレッドを強制終了することは可能ですが、一般的には安全な停止パス、つまりある種の中止ブランチが必要です。
これは JSL で実行できますが、次のいずれかが必要です。待って( ... )ステートメントまたは<<ウィンドウを更新()どちらのステートメントも重大な結果をもたらす可能性があります。特に、スクリプト内の変数名を破壊する可能性のあるイベント ループ中に意図せず実行されるコードが存在する可能性があります。これは、たとえば、グラフィックス スクリプトがグラフ上に存在し、実行される場合に発生する可能性があり (JMP はグラフィックス スクリプトを非常に積極的に実行します)、これらのスクリプトは、制御できない他のアドインからユーザーのシステム上に存在する可能性があります。確かに、スクリプトが完了するまでは決してイベント ループに実行を戻さないことが最善です (そして明らかに、JMP がフリーズしたように見えるのを避けるためにスクリプトをできるだけ短くしておきます)。端的に言えば、実行をイベント ループに戻さないことです。
個人的には、現時点 (もうすぐ 2022 年です!) の時点で JSL 内にマルチスレッド実行パラダイムがないのは、JMP チームの少々短絡的だと思いますが、それは事実です。
注意すべき点が 1 つあります。外部プログラムを実行し、STDOUT を介して IPC 経由で外部プログラムと通信することができます。たとえば、Python を使用してある種の長時間実行される作業を実行し、STDOUT を使用してそれがいつ終了したかを知ることができます (また、ある種の STDOUT センチネルで JMP スクリプトを開始することもできます)。
Re: プログレスバーの作成に関する質問はい。 ボタン スクリプトは独自の「コンテキスト」で実行されます。 wait ステートメントを実行している別のスクリプトがあることを知りません。 グローバル経由で通信できます。 そして、奇妙な可能性を終わらせるために、ボタン スクリプトで待機を使用すると、スクリプトを実行しているウィンドウで閉じる X をクリックできることになります...待機が終了すると、jmp はスクリプトを安全に停止しようとします。 通常、待機中にボタン スクリプトを保持しているウィンドウが閉じられた場合、待機後の次のステートメントは実行されません。
編集: また、キャンセルボタンのクリックを処理するには待機が必要です。
Re: プログレスバーの作成に関する質問こんにちは、クレイジ! ありがとう。 明確にしておきますが、私が追加した「Wait(1)」は、このデモ用に長いコマンド セットの実行を模倣するためだけであり、問題を再現できるように「キャンセル」をクリックするのに十分な時間を与えるためでした。 ただし、Wait がスクリプトの必須部分であることは意図していませんでした。
あなたが言っていることを要約してみると、次のようになります。
[キャンセル] ボタンは、スクリプト A (For ループを含むメイン スクリプト) とは独立したスクリプト B を呼び出します。 スクリプト B の Stop コマンドはスクリプト B の実行を停止できますが、スクリプト A には影響しません。
それは正しいですか、多いか少ないですか?
Re: プログレスバーの作成に関する質問wait( n ) は JMP では必要悪であり、可能な限り避けるべきです。 待機中、wait を呼び出すスクリプトは一時停止され、OS はクリックの認識や開いているウィンドウの表示などの処理を実行できます。 クリックを使用して、最初のスクリプトの環境に影響を与える別のスクリプト (あなたの例) を開始できるため、奇妙なことが起こる可能性があります。 あなたの例では、stop() は 2 番目のスクリプトを停止しています。 グローバルフラグを設定することもできます。 プロジェクトが大規模でグローバル変数の追跡が心配な場合は、名前空間を使用することもできます。
それで、起こり得る奇妙なことは何ですか? ほとんどの場合、ウィンドウが閉じられているか、ディスプレイボックスが削除されています。 特に、wait(1) を使用するスクリプトを含むクリック関数で、0.5 秒後にもう一度ボタンをクリックするとします。 スクリプトの 2 番目のコピーが最初のスクリプト内で実行されています。 元の wait(1) は、2 番目のスクリプトが終了するまで戻りません。 2 番目のスクリプトがボタンが存在するウィンドウを閉じる場合、元のスクリプトの周囲にはどのような環境があるでしょうか? (待機前と同じではありません!) 正当な理由なしに待機を必要とするスクリプトを構築しないでください。ほとんどの場合、displaybox<<Re: プログレスバーの作成に関する質問
他に興味深いことに気づきました。 キャンセル ボタン スクリプト内の「pwin << Close Window()」コマンドをコメント アウトすると、キャンセル ボタンは実行を停止しなくなりました。 Stop() コマンドは、ボタンから実行された場合、For ループを停止できないようです。 以前は、ウィンドウの削除でエラーが発生したためのみ、「キャンセル」ボタンで実行を停止できました。
Re: プログレスバーの作成に関する質問ライアン(そしてクレイジ)に感謝します。 これは私が確実に検討しているオプションの 1 つですが、スクリプト本体の if 句にフラグを送信する必要があります。 私の希望は、[キャンセル]ボタンのStop()コマンドを使用してプログラムの実行を停止することです。 もしかしたら、私の質問を言い換えることができるかもしれません。Stop() コマンドが実行を停止しないように見えるのはなぜですか?
Re: プログレスバーの作成に関する質問やあ@ニクルズ。 この最近の投稿をチェックしてみてください。 @Craige_Hales 、キャンセルボタン付きのプログレスバー。