2016-09-25 8 views
1

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; 
} 
+0

は、これらすべての文が何をしているかIDKが、高価なタスクは 'Task'sの' call'方法で行う必要があります。私はあなたが 'onSucceeded'ハンドラから結果を得るのを見ません。メソッド名から推測すると、 'parseRegTask'の' onSucceeded'ハンドラで実行されるのは 'updateMainComponents();'だけです。 – fabian

+0

ありがとうファビアン。それは私の問題を解決したようです。あなたが望むなら、この質問を閉じるための答えとしてそれを書くことができます。私はそれがなぜ起こっていたのか(なぜなら、仮説的にさえ)を知りたいのです。 – pror21

+0

IntelliJのバグではありません。最初に、最後に、そしていつも自分を疑ってください。 – duffymo

答えて

1

onSuceededハンドラがJavaFXアプリケーションのthead要素に呼び出されます。ここでは長時間実行する操作は不要です。ここではUIの更新のみを行うことをお勧めします。 Taskの結果を使用して、操作の結果を「公開」することができます。この値は、onSucceededハンドラで取得できます。

あなたのコードでは、UIスレッドをブロックするonSucceededハンドラでこれらの操作を実行しています。

次の例は、適切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(); 
} 
+0

updateProgressとupdateMessage()をcall()の内部で使用できますか?私はこれらのメソッドの命名から、主なJavaFXスレッドのプロパティを変更していると思います。 – pror21

+0

@ pror21私は 'call'メソッドでこれらのメソッドを使用していますか?実際には、別のスレッドで実行されていても、このメソッドから呼び出すことができます。https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html#updateProgress-long-long- https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html#updateMessage-java.lang.String- – fabian

+0

これらのメソッドがタスク・クラスの一部であることはわかりませんでした。面白い!再度、感謝します – pror21

関連する問題