如何使Task的updateMessage()立即生效?

时间:2012-06-27 12:17:38

标签: multithreading javafx javafx-2

我正在使用JavaFx API的Task class来执行网络操作。该类提供了一个似乎完全适应这种情况的进度系统,例如,允许报告上传到调用者线程的文件数量。为此,每次成功上传文件时都会调用updateMessage(x + "files uploaded")

问题是我收到的唯一信息是最后一条,当每个文件都被上传时。我想Javadoc以某种方式解释了这种现象:

  

对updateMessage的调用将在FX应用程序线程上合并并稍后运行,因此即使从FX Application线程调用updateMessage也不一定会立即更新此属性,并且可以合并中间消息值以节省事件通知。

如何正确报告每条或至少部分消息?我试图在它周围添加一些Thread.sleep(20),但它不起作用。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

很可能你在事件线程上运行Task,所以它会阻止更新。任务实现了Runnable,这有点误导,但通过查看javadoc,你可以发现正确运行Task的方法是将它分配到新线程:new Thread(task).start();

见下一个例子:

public class TaskTask extends Application {
    public static void main(String[] args) { launch(args); }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle(VersionInfo.getRuntimeVersion());
        Button btn = new Button();

        final Task<Integer> task = new Task<Integer>() {
            @Override
            protected Integer call() throws Exception {
                int iterations;
                for (iterations = 0; iterations < 100; iterations++) {
                    if (isCancelled()) {
                        break;
                    }
                    Thread.sleep(100); // imitate activity
                    updateMessage("Iteration " + iterations);
                }
                return iterations;
            }
        };

        // here we monitor task updates
        btn.textProperty().bind(task.messageProperty());

        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                //here it goes
                new Thread(task).start();
            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(btn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();

    }
}

答案 1 :(得分:1)

好吧,我的错。我错误地收听了消息更新:我在Task上使用了EventHandler,而不是在messageProperty上使用了ChangeListener。 javadoc只指示如何发送更新,而不是接收更新,所以我尝试了,但谢尔盖的答案是正确的方法。