任务悬而未决

时间:2016-09-25 13:03:30

标签: java multithreading intellij-idea javafx

当我通过IntelliJ(最新版本)运行应用程序时,我的上一个任务将永远挂起。 实际上我试图调试它挂在fetchRegisterCourseList()上。 我可以看到它悬挂,因为我有一个进度指示器,从未获得特定数据。 另一方面,当我将我的应用程序打包到jar并正常执行时,它永远不会挂起,一切正常。

这是与IntelliJ或代码相关的错误吗?

AuthController:

        ... // previous tasks

        Task<List<Course>> parseGradesTask = new Task<List<Course>>() {
            @Override
            public List<Course> call() {
                return studentParser.parseStudentGrades();
            }
        };

        Task<HashMap<String, String>> parseRegTask = new Task<HashMap<String, String>>() {
            @Override
            public HashMap<String, String> call() {
                return studentParser.parseStudentRegistration();
            }
        };

        parseGradesTask.setOnSucceeded(e -> {
            serializeService.serializeCourses(parseGradesTask.getValue());
            progressIndicator.setProgress(0.6);
        });

        parseRegTask.setOnSucceeded(e -> {
            // it is hanging at this line:
            List<Course> regList = serializeService.fetchRegisterCourseList(parseGradesTask.getValue(), parseRegTask.getValue());
            serializeService.serializeRegister(regList);
            updateMainComponents();
        });

        ExecutorService es = Executors.newSingleThreadExecutor();
        es.submit(parseInfoTask);
        es.submit(parseGradesTask);
        es.submit(parseStatsTask);
        es.submit(parseRegTask);
        es.shutdown();

private void updateMainComponents() {
    MainController.getInstance().updateAllViewComponents();

    if (preferenceService.getPreferences().getPrefSyncEnabled()) {
        SyncScheduler.getInstance().stopScheduler();
        SyncScheduler.getInstance().startSyncScheduler(preferenceService.getPreferences().getPrefSyncTime());
    }
    dialogStage.close(); //close this window
}

serializeService:

public List<Course> fetchRegisterCourseList(List<Course> courseList, HashMap<String, String> courseIdList) {
    List<Course> courseRegList = new ArrayList<>();

    Iterator it = courseIdList.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pair = (Map.Entry) it.next();
        courseRegList.addAll(courseList.stream().filter(course ->
                course.getCourseId().equals(pair.getKey()) && course.getCourseTitle().equals(pair.getValue()))
                .collect(Collectors.toList()));
        it.remove(); // avoids a ConcurrentModificationException
    }
    return courseRegList;
}

1 个答案:

答案 0 :(得分:1)

在JavaFX应用程序上调用onSuceeded处理程序。这里不应该进行长期运行。最好只在这里进行UI更新。 Task的结果可用于&#34;发布&#34;操作的结果。可以在onSucceeded处理程序中检索此值。

在您的代码中,您在onSucceeded处理程序中运行这些操作,这会阻止UI线程。

以下示例显示了如何正确使用Task

@Override
public void start(Stage primaryStage) {
    TextArea textArea = new TextArea();
    Button button = new Button("Get Text");
    button.setOnAction(evt -> {
        button.setDisable(true);
        Task<String> task = new Task<String>() {

            @Override
            protected String call() throws Exception {
                // do long-running operations not modifying the UI
                // here
                StringBuilder sb = new StringBuilder();

                final int count = 10;

                for (int i = 0; i < count; i++) {
                    // update message & progress
                    // the messageProperty / progressProperty will be modified on
                    // the javafx application thread
                    updateProgress(i, count);
                    updateMessage("Loading part " + (i+1));

                    // simulate long-running operation
                    Thread.sleep(500);
                    sb.append('\n').append(i);
                }
                updateProgress(count, count);
                return sb.toString();
            }

        };

        // while loading, display the task message in the TextArea
        textArea.textProperty().bind(task.messageProperty());

        task.setOnSucceeded(succeededEvent -> {
            // only modifications of the UI here, no longrunning tasks
            textArea.textProperty().unbind();

            // use result of the task
            textArea.setText(task.getValue());

            button.setDisable(false);
        });

        // run task on different thread
        new Thread(task).start();
    });

    Scene scene = new Scene(new VBox(textArea, button));

    primaryStage.setScene(scene);
    primaryStage.show();
}