EDIT :我最初认为此问题是由ifPresentOrElse
语句引起的,但是我现在知道并非如此而无限的while循环是这种行为的罪魁祸首,并且已将问题重命名(请参阅评论和选择的答案)。
存在一个现有的问题here,与此问题具有相似的行为,但是我认为解决方案足够不同,因此不能被视为重复项。
原始问题:
假设我有一个JavaFX应用程序,其启动方法(在应用程序线程中)包含以下代码:
while(true) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
Platform::exit);
}
其行为应是,如果按下 TextInputDialog 的 OK 按钮(显示结果),则应打印对话框中输入的文本。如果按下 CANCEL 按钮,将调用Platform::exit
语句,并且JavaFX应用程序将退出。
前一种情况按预期工作,但后一种情况不起作用。如果按下 CANCEL 按钮,该应用程序将保持活动状态,并再次打开该对话框,就像按下 OK 按钮一样,但是不会打印任何文本,这意味着必须到达Platform::exit
语句,而不是System.out::println
语句。为了调试此问题,我将原始代码调整为以下代码:
while(true) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> System.out.println("The latter statement has been reached"));
}
运行此代码并按 CANCEL 按钮时,“已到达后面的语句” 会显示在屏幕上,证明Platform::exit
可以通过原始代码访问,但未按预期关闭应用程序。
有趣的是,如果我再次将原始代码编辑为以下内容:
while(true) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> System.exit(0));
}
...程序按预期退出。
我以前从未遇到过这样的行为,而我对发生的事情确实感到茫然。任何见识将不胜感激。
答案 0 :(得分:5)
阅读Platform.exit()
的文档:
导致JavaFX应用程序终止。如果在调用Application start方法之后调用此方法,则JavaFX启动程序将调用Application stop方法并终止JavaFX应用程序线程。然后启动器线程将关闭。如果没有其他非守护程序线程在运行,则Java VM将退出。如果从Preloader或Application init方法调用此方法,则可能不会调用Application stop方法。
可以从任何线程调用此方法。
可以看出,调用该方法不会杀死线程,因此运行您的while(true)
循环的线程将继续运行,并防止程序结束。
您需要更改代码,以便while
循环也结束,例如像这样的东西:
AtomicBoolean keepRunning = new AtomicBoolean(true);
while (keepRunning.get()) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> keepRunning.set(false));
}
Platform.exit();