0

各位程序员好。

所以我终于开始使用 JavaFX 并发现一些看起来不太正确的东西。如果我覆盖我的任务的 call() 方法然后运行它,则此任务的状态将在调用完成后开始更新。

我的代码看起来像这样

Task<Boolean> myTask = new Task<Boolean>() {
    @Override
    protected Boolean call() throws Exception {
        try {
             // do stuff
             return true;
        } catch (Exception e){
             return false;
        }
    }
}

在 try 块中,我有一些调用需要几秒钟才能完成,我不希望我的 GUI 在那段时间内简单地阻塞。然而,由于无法进一步进步,我使用了 ControlsFX 库并制作了一个显示该进度的进度对话框。(对话独库

此对话框需要一个 Worker,然后将显示进度。一旦 Worker State 更改为 Scheduled 或 Running,它将自动显示。我现在的问题是这个对话框永远不会显示,因为在状态更改为其中之一之前调用了调用方法。

我做了一些调试,似乎在 Task 类中,State 更改将通过 Platform.runLater() 方法应用,然后 call() 方法被直接调用(没有 runLater),我的系统似乎在 State 更改之前安排了这个.

所以我的问题是,有人可以重现或有类似的问题吗?如果是,Task 类是否按预期工作或者这可能是一个错误(比如 call() 也必须通过 runLater 方法调用)?

非常感谢您的帮助:) 请原谅我的第二语言英语

这是Task类的代码

task.runLater(() -> {
    task.setState(State.SCHEDULED);
    task.setState(State.RUNNING);
});
 // Go ahead and delegate to the wrapped callable
try {
    final V result = task.call();
    if (!task.isCancelled()) {
        task.runLater(() -> {
        task.updateValue(result);
        task.setState(State.SUCCEEDED);
    });
    return result;

现在我期望的顺序是在执行 call() 方法之前将状态设置为首先 SCHEDULED 然后 RUNNING 。然而,在我的情况下,它总是先调用(),然后再过一段时间它会改变状态。

例子:

package test;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.stage.Stage;

public class TaskTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Task<Void> myTask = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                System.out.println("Executing stuff");
                return null;
            }
        };

        myTask.stateProperty().addListener(new ChangeListener<Worker.State>() {

            @Override
            public void changed(
                    ObservableValue<? extends javafx.concurrent.Worker.State> observable,
                    Worker.State oldValue,
                    Worker.State newValue) {
                System.out.println("State change: " + oldValue + " -> " + newValue);

            }
        });

        Executors.newSingleThreadExecutor().execute(myTask);

        try {
            myTask.get();
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        launch(args);
    }
}

结果:

Executing stuff
State change: READY -> SCHEDULED
State change: SCHEDULED -> RUNNING
State change: RUNNING -> SUCCEEDED

预期的:

State change: READY -> SCHEDULED
State change: SCHEDULED -> RUNNING
Executing stuff
State change: RUNNING -> SUCCEEDED
4

0 回答 0