Platform.exit() 在 JavaFX 的无限循环中无效
Platform.exit() has no effect within infinite loop in JavaFX
EDIT: 我原本认为这个问题是由 ifPresentOrElse
语句引起的,但现在我明白了,事实并非如此并且无限循环是造成这种行为的罪魁祸首,并已重命名问题(参见评论和选择的答案)。
有一个现有问题 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按钮时,"The latter statement has been reached"会打印到屏幕上,证明在原始代码中达到了 Platform::exit
,但没有按预期关闭应用程序。
有趣的是,如果我再次将原始代码编辑为以下内容:
while(true) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> System.exit(0));
}
...程序按预期退出。
我从来没有遇到过这样的行为,我真的不知道这是怎么回事。任何见解将不胜感激。
阅读 Platform.exit()
的文档:
Causes the JavaFX application to terminate. If this method is called after the Application start method is called, then the JavaFX launcher will call the Application stop method and terminate the JavaFX application thread. The launcher thread will then shutdown. If there are no other non-daemon threads that are running, the Java VM will exit. If this method is called from the Preloader or the Application init method, then the Application stop method may not be called.
This method may be called from any thread.
可以看出,调用该方法不会杀死线程,因此 运行 在您的 while(true)
循环中的线程将继续 运行,并且会阻止程序结束.
您需要更改代码以便 while
循环也结束,例如像这样:
AtomicBoolean keepRunning = new AtomicBoolean(true);
while (keepRunning.get()) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> keepRunning.set(false));
}
Platform.exit();
EDIT: 我原本认为这个问题是由 ifPresentOrElse
语句引起的,但现在我明白了,事实并非如此并且无限循环是造成这种行为的罪魁祸首,并已重命名问题(参见评论和选择的答案)。
有一个现有问题 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按钮时,"The latter statement has been reached"会打印到屏幕上,证明在原始代码中达到了 Platform::exit
,但没有按预期关闭应用程序。
有趣的是,如果我再次将原始代码编辑为以下内容:
while(true) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> System.exit(0));
}
...程序按预期退出。
我从来没有遇到过这样的行为,我真的不知道这是怎么回事。任何见解将不胜感激。
阅读 Platform.exit()
的文档:
Causes the JavaFX application to terminate. If this method is called after the Application start method is called, then the JavaFX launcher will call the Application stop method and terminate the JavaFX application thread. The launcher thread will then shutdown. If there are no other non-daemon threads that are running, the Java VM will exit. If this method is called from the Preloader or the Application init method, then the Application stop method may not be called.
This method may be called from any thread.
可以看出,调用该方法不会杀死线程,因此 运行 在您的 while(true)
循环中的线程将继续 运行,并且会阻止程序结束.
您需要更改代码以便 while
循环也结束,例如像这样:
AtomicBoolean keepRunning = new AtomicBoolean(true);
while (keepRunning.get()) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> keepRunning.set(false));
}
Platform.exit();