Platform.runLater が現在 JavaFX スレッド上にあるかどうかをチェックしないのはなぜですか?
質問
JavaFX 8 を使用する場合、GUI との対話を実行する必要があります。 Platform.runLater
, そうでない場合、別のスレッドから実行すると例外がスローされます。
ただし、実装は Platform.runLater
現在 JavaFX スレッド上にあるかどうかは決してチェックしません。
次のメソッドを書きました。
public static void runSafe(final Runnable runnable) {
Objects.requireNonNull(runnable, "runnable");
if (Platform.isFxApplicationThread()) {
runnable.run();
}
else {
Platform.runLater(runnable);
}
}
これにより、fx アプリケーション以外のスレッドでは実行できなくなります。
デフォルトの実装がこの種の短絡を行わない理由はありますか?
解決
runLater
基本的に、FX スレッドが使用可能になったときに Runnable を実行用のキューに入れます。このメソッドには、FX 以外のスレッドを通じてアクセスできます。他のスレッドがタスクを runLater
キューに入れてから電話をかける runLater
この場合も、FX スレッドからかどうかに関係なく、新しいタスクをそのキューの末尾に配置する必要があります。
あなたが提案する短絡では、以前のタスクの優先順位は基本的に低くなり、望ましくない可能性があります。
他のヒント
関数を呼び出すとき、その関数が 'runLater' と呼ばれる場合、それは今ではなく後で実行されることが期待されます。
名前からすると、実装は正しいことをしているように思えますが、 そしてそれはドキュメントです:
将来の不特定の時点で、JavaFX アプリケーション スレッド上で指定された Runnable を実行します。
このメソッドは任意のスレッドから呼び出すことができ、Runnable をイベント キューにポストし、すぐに呼び出し元に戻ります。ランナブルは、投稿された順序で実行されます。runLater メソッドに渡された Runnable は、後続の runLater 呼び出しに渡された Runnable よりも前に実行されます。
コードを後で実行したくない場合は、後で実行するように要求しないでください。これがコードで本質的に行ったことです。
電話をかけている人を見たことがある EventQueue.invokeLater
Swing の EDT から時々...規範によれば、それは合法的な技術です。したがって、私がよほど間違っていない限り、これは JavaFX でも同じ状況です。
しかし、個人的にはこの手法には疑問を感じます。見る この質問:選択された答えは使用します invokeLater
なぜなら selectAll()
呼び出される前に、現在のすべての EDT イベントが自動的に完了する必要があります。このソリューションは実際に次のことを保証します selectAll
ここで他の EDT コードが発生する前に実行することはできません。
しかし、この答えには脆弱性があると私は主張します。私が提案した答えを参照してください(Jythonで書かれていますが、理解できるはずです)。誰かが「編集を開始するためのクリック数」を 1 に設定したとします。さらに恐ろしいことに、二人の間で何か予期せぬことが起こったとします。 invokeLater
そしてその selectAll
. 。代替メカニズムがまったくないという確信がある場合、または 2 つのスレッドのイベントとオブジェクトが完全に「切り離されている」という確信がある場合を除き、個人的には呼び出すことは避けるべきだと思います。 runLater
JavaFX スレッドから。
同時実行性は常にあなたを攻撃するのを待っています。したがって、このようなテクニックは細心の注意を払って使用してください。