【问题标题】:Running a process in a separate thread so rest of Java FX application is usable?在单独的线程中运行一个进程,以便 Java FX 应用程序的其余部分可用?
【发布时间】:2017-11-07 23:28:44
【问题描述】:

我目前正在创建一个带有使用 Java FX 创建的 UI 的 Java 应用程序。我的应用程序界面分为三个单独的选项卡。在第一个选项卡上,我有很多用于启动其他应用程序的按钮。我的目标是让用户按特定顺序启动这些应用程序,因此后续按钮被禁用,直到前一个应用程序的进程完成,然后它们才被启用。我已经通过使用这些行来实现这一点

Process p = Runtime.getRuntime().exec(application);
p.waitFor();

然后控制器启用界面中的下一步按钮。我的问题是在启动的应用程序运行时出现的。由于我的应用程序正在等待进程结束,任务管理器将我的 Java 应用程序显示为没有响应,并且您无法导航到其他选项卡。当然,当启动的应用程序完成后,我的应用程序就可以正常运行了。

我认为这是由于主线程在等待进程完成时被阻塞。最好的解决方案是在单独的线程上运行此进程,以便应用程序的其余部分在等待启动的进程完成时可用?

【问题讨论】:

  • 是的。最好将您的 UI 与长时间运行的操作保持在单独的线程中。

标签: java multithreading javafx


【解决方案1】:

我在想这是因为主线程在等待进程完成时被阻塞了。

这是正确的。

是否可以在单独的线程上运行此进程,以便在等待启动的进程完成时应用程序的其余部分可用?

是的,当然。最简单的做法就是在单独的线程上启动它:

Process p = Runtime.getRuntime().exec(application);
new Thread(p::waitFor).start();

但是,您可能还需要更多:例如当新线程完成等时收到通知。JavaFX 提供了一个concurrency API,它具有针对您执行的任务的生命周期的回调。这些回调在 FX 应用程序线程上执行,因此在回调中更新 UI 是安全的(您不能从后台线程更新 UI)。

所以你可以做类似的事情

Task<Void> executeAppTask = new Task<Void>() {
    @Override
    protected Void call() throws Exception {
        Process p = Runtime.getRuntime().exec(application);
        p.waitFor();
        return null;
    }
};

executeAppTask.setOnSucceeded(e -> {
    /* code to execute when task completes normally */
});

executeAppTask.setOnFailed(e -> {
    Throwable problem = executeAppTask.getException();
    /* code to execute if task throws exception */
});

executeAppTask.setOnCancelled(e -> {
    /* task was cancelled */
});

Thread thread = new Thread(executeAppTask);
thread.start();

请注意,setOnSucceeded()setOnFailed()setOnCancelled() 处理程序在 FX 应用程序线程上执行,因此在这些处理程序中更新 UI 是安全的。另请注意,如果需要,调用executeAppTask.cancel() 将中断运行任务的线程,这将正确中断waitFor() 方法。因此,您将(或多或少)通过调用executeAppTask.cancel() 立即调用setOnCancelled 处理程序。如果call() 方法中有代码在调用阻塞方法之后执行,例如waitFor(),它应该可能会捕获中断的异常并检查isCancelled() 标志,如果出现以下情况则优雅退出任务已取消。

更多示例请参见Task API docs

【讨论】:

猜你喜欢
  • 2018-11-18
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多