javafx - 关闭对话框时取消任务

时间:2015-09-21 20:13:04

标签: java multithreading user-interface task

在javafx应用程序中,我有一个方法trainingin(String),由于天真的实现(教育),需要很长时间才能进行大量输入。我正在加载时打开一个对话框,我希望用户能够取消/关闭对话框,任务将退出。有没有办法做到这一点,而不传递对重新训练的任务的引用。现在我认为当我取消线程被取消但重新训练仍然在后台运行。

任何提示都将不胜感激!

@FXML
        private void handleMarkovText() {
            textgen.MarkovTextGenerator mtg = mainApp.getMTG();
            Task<textgen.MarkovTextGenerator> task = new Task<textgen.MarkovTextGenerator>() {
                @Override
                public textgen.MarkovTextGenerator call() {
                    // process long-running computation, data retrieval, etc...

                mtg.retrain(textBox.getText());
                return mtg;
            }
        };

        Dialog<Void> loadDialog = new Dialog<Void>();
        loadDialog.setOnCloseRequest( e -> {
            //if(task.isRunning()) {
                task.cancel();

            //}
        });

        loadDialog.setContentText("Training MTG...");

        task.setOnRunning( e -> {
            ButtonType cancelButtonType = new ButtonType("Cancel", ButtonData.CANCEL_CLOSE);
            //Dialog<Void> loadDialog = new Dialog<Void>();
            loadDialog.getDialogPane().getButtonTypes().add(cancelButtonType);
            loadDialog.show();
            if(task.isCancelled()) {
            }
        });


        task.setOnSucceeded(e -> {
            loadDialog.close();
            textgen.MarkovTextGenerator result = task.getValue();
            mainApp.showMarkovDialog(result);
            // update UI with result
        });

        task.setOnCancelled(e -> {
            System.out.println("Cancelled");
        });

        task.setOnFailed(e -> {
            //System.out.println("failed");
        });
        //ProgressBar bar = new ProgressBar();
        //bar.progressProperty().bind(task.progressProperty());
       Thread thread  = new Thread(task);
       thread.start();





        // train/retrain markov
        // show results

    }

1 个答案:

答案 0 :(得分:1)

使用retrain方法

处理任务取消

您的retrain方法需要了解任务取消状态。它可以通过在适当的时间轮询task.isCancelled来实现。如果它检测到取消,则重写方法可以自行清理(释放它正在消耗的任何资源并确保取消的状态在语义上与您的应用程序一致)并且不进行任何进一步处理(有效地允许执行重写的线程退出) 。

示例代码

取消检查的示例代码在Task文档中提供,标题为:&#34;带有进度通知和阻止呼叫的简单循环&#34;。

背景资料

来自任务javadoc的相关信息:

  

在Java中,没有可靠的方法来杀死&#34;正在进行的一个线程但是,在Task上调用cancel时,任务停止处理很重要。 A&#34;逃跑&#34;即使在取消任务后,任务仍可继续处理和更新消息,文本和进度属性!在Java中,取消任务是一项合作努力。任务的用户将请求取消它,并且任务的作者必须检查是否已在调用方法的主体内取消。有两种方法可以做到这一点。首先,Task作者可以检查继承自FutureTask的isCancelled方法,以查看Task是否已被取消。其次,如果Task实现使用任何阻塞调用(例如NIO InterruptibleChannels或Thread.sleep)并且在这样的阻塞调用中取消了任务,则抛出InterruptedException。具有阻塞调用的任务实现应该认识到中断的线程可能是取消任务的信号,并且应该仔细检查isCancelled方法以确保由于取消任务而抛出InterruptedException。

使用线程的中断状态

如果您不想让retrain方法引用任务API(因为您希望将其与JavaFX任务API分离或出于其他原因),您可能能够实现类似通过task.isCancelled方法中的适当位置调用Thread.currentThread().isInterrupted()来检查retrain行为。

下面列出的Goetz文章中的清单5:PrimeProducer就是这种方法的例子。

JavaFX Tasks,实现futureTask,因此您可以在mayInterruptIfRunning设置为true的情况下调用cancel(boolean mayInterruptIfRunning),并且应该在执行任务的线程上设置中断状态(在您的情况下,它将执行rewrite方法。)

处理线程工作取消的一般程序的背景资料:Java theory and practice: Dealing with InterruptedException(Brian Goetz的文章。

注意:是否使用任务取消或线程中断状态检查,在任何一种情况下都需要自定义rewrite方法,您需要修改该方法以使其处理取消或中断适当。