【问题标题】:how to stop "JavaFX Application Thread"如何停止“JavaFX 应用程序线程”
【发布时间】:2013-03-26 08:12:09
【问题描述】:

我有一个简单的控制台应用程序,有时需要执行图形操作,对于那些我正在使用 JavaFx 框架的应用程序(我需要一些功能,例如 text 的 css 样式) 我只是将一些形状和文本生成到一个隐藏的场景中,然后将它们保存在文件中,仅此而已,

我知道要使用 JavaFx,我必须将图形操作传递给 JavaFx 线程,但是当一切都完成后我必须关闭应用程序(几个小时后)这个 JavaFx 线程仍然保持打开状态......我真的不想用 System.exit() 强制退出,因为如果有东西被阻止我可能想知道/等待(另外我不想将所有东西作为 JavaFx 应用程序执行(因为 JavaFx 组件不到我的 1%主应用)

代码非常简单,我用谷歌搜索发现只能使用

Platform.exit();

这似乎不起作用,我也尝试过使用平台参数,例如

Platform.setImplicitExit(false);

这是我可以运行的测试应用程序:

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.Pos;
import javafx.scene.layout.VBox;

public class SOTestFX {
    public static void main(String[] args) {
        SOTestFX t = new SOTestFX();
        t.runFxThread();
    }

    public  void runFxThread(){
        //Application.launch(args);
        final JFXPanel jfxPanel = new JFXPanel(); 
        Platform.runLater(new Runnable() {
            @Override
            public void run() {

                System.err.println("CREATING IMAGE");
                simpleFXoperations();
                System.err.println("NOW CALL EXIT");
                System.err.println("JAVA FX THREAD SHOULD BE EXITED NOW");
                Platform.exit();
            }
        });

        try {
            Thread.sleep(3000); // just wait a bit if something should happen, let it happen..
        } catch (InterruptedException e) {
            e.printStackTrace();  
        }
        //jfxPanel.removeNotify(); // return ->  java.lang.NullPointerException
        //Platform.exit(); // -> does nothing

        System.err.println("i will never die!");
    }
    public void simpleFXoperations(){

        VBox vbox1 = new VBox();
        vbox1.setAlignment(Pos.BOTTOM_CENTER);
        vbox1.setStyle("-fx-border-style: solid;"
                + "-fx-border-width: 1;"
                + "-fx-border-color: white");
        System.err.println("simpleFXoperations() _DONE");
    }
}

这是永远不会关闭的线程

“附加监听器” - 线程 t@17 java.lang.Thread.State: RUNNABLE

锁定的可拥有同步器: - 无

“JavaFX 应用程序线程” - 线程 t@13 java.lang.Thread.State: 在 com.sun.glass.ui.gtk.GtkApplication._runLoop (Native 方法)在 com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:82) 在 java.lang.Thread.run(Thread.java:722)

锁定的可拥有同步器: - 无

更新:我在 Linux Fedora 16 64 位上使用最新的 Oracle JDK 7u17 64 位。

【问题讨论】:

  • 我对此没有任何答案,也不知道为什么Platform.exit 不适用于您的测试用例。尝试在javafx-jira.kenai.com 提交问题
  • 谢谢,但它对你有用吗?你有类似的测试用例吗?在我所有的测试中,似乎 Platform.exit() 根本不起作用.. :(

标签: java javafx-2 javafx


【解决方案1】:

修复:

我可以通过在Platform.exit() 之前立即调用com.sun.javafx.application.PlatformImpl.tkExit() 来解决此问题。我不太了解 JavaFX 源代码,但它似乎在工作; YMMV。

更新:在 Java 8 中执行此操作会产生警告,您可以使用 @SuppressWarnings("restriction") 关闭警告。应该没问题。

解释:

我通过挖掘源代码发现了这一点; JFXPanel 有这个小 sn-p(来自 JavaFX 2.2.25)

finishListener = new PlatformImpl.FinishListener() {
  public void idle(boolean paramAnonymousBoolean) {
    if (!JFXPanel.firstPanelShown) {
      return;
    }
    PlatformImpl.removeListener(JFXPanel.finishListener);
    JFXPanel.access$102(null);
    if (paramAnonymousBoolean)
      Platform.exit();
  }

  public void exitCalled()
  {
  }

问题是,如果您在应用程序中只使用一点点 JavaFX,那么 idle(boolean) 方法永远不会做任何事情(因为 firstPanelShown == false),这会阻止侦听器被删除,从而阻止 JavaFX @ 987654329@ from shutdown... 这意味着您必须手动将其关闭。

【讨论】:

  • 这是有道理的,部署应用程序时无济于事。我已经看到 JavaFX 应用程序终止,但它仍然通过 NetBean 任务状态在后台主动运行。在运行(或活动)时。如果不重新启动,您将无法删除 JAR 或重新启动应用程序!
  • 依赖com.sun 方法不是我想做的事情。尤其是不考虑 OpenJDK 和/或 Java 9。
  • 我已经阅读了 this 咆哮的你的元答案,并认为你的辛勤工作不应该被忽视。所以,我正在尽我所能:+1 :-)
  • 抛出java.lang.IllegalStateException: Toolkit has exited
  • @kuhaku 这个答案完全有可能已经过时了,当你进行内部的、未记录的 API 调用时可能会发生这种情况:-/
【解决方案2】:

您的 main 函数不属于 JavaFx Application 对象,我认为您的程序永远不会进入应用程序线程循环。

看来你应该这样做:

public class SOTestFX extends Application {
    public static void main(String[] args) {
        launch(args);
    }
    @Override
    public void start(Stage stage) throws Exception {
        // Do stuff here to show your stage or whatever you want;
        // This will be called on the JavaFX thread
    }
}

【讨论】:

  • 但我不想仅仅因为我需要处理一些图像的小类(少于 800 行)需要 JavaFX 就包含整个应用程序(超过 40k 行代码) ,该应用程序甚至不是图形它是一个控制台应用程序,还是谢谢你
  • 看来确实是这个问题,看一下在Application的lauch方法中调用的LauncherImpl的源码:bitbucket.org/openjfxmirrors/openjfx-8-graphics-rt/src/…
【解决方案3】:

这是一个棘手的情况,因为(据我所知)JavaFX 线程的目的是透明地利用各种硬件管道。我可以建议将您的 JavaFX 请求放在一个单独的、引用的项目中吗?并将其他所有内容(包括您的主要方法)保存在另一个中?这一直对我有用。

基本上,业务逻辑和模型放在一个项目中,而视图和控制(通常基于 JavaFX)则放在另一个项目中。这允许独立终止 JavaFX 线程。希望这适用于您正在尝试做的事情。

【讨论】:

  • 是的,同意分离。但是,例如,当您希望控制台应用程序的用户选择文件时,您会怎么做?您肯定会允许他们使用 FileChooser,而无需 Stage? PS 我目前发现 Platform.exit() 可以很好地关闭 JavaFX 线程。
【解决方案4】:

我在这方面尝试了很多东西,因为上述答案都不适合我。 对我来说最好的事情是关闭整个 JVM 使用

System.exit(1);

因为我的整个应用程序只是一个 JavaFX 应用程序,因此可以在关闭舞台时关闭。 在我的例子中 1 只是一个随机整数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多