JavaFX SwingWorker Equivalent

javajavafxmultithreadingthread-safetyworker

Is there a JavaFX equivalent to the Java SwingWorker class?

I am aware of the JavaFX Task but with that you can only publish String messages or a progress. I just want to call a method in the GUI thread like I would have done with the SwingWorker (by publishing messages of an arbitrary type).

Heres is an example of what I mean:

class PrimeNumbersTask extends
         SwingWorker<List<Integer>, Integer> {
     PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
         //initialize
     }

      @Override
     public List<Integer> doInBackground() {
         while (! enough && ! isCancelled()) {
                 number = nextPrimeNumber();
                 publish(number);
                 setProgress(100 * numbers.size() / numbersToFind);
             }
         }
         return numbers;
     }

      @Override
     protected void process(List<Integer> chunks) {
         for (int number : chunks) {
             textArea.append(number + "\n"); // HERE: execute in GUI thread
         }
     }
 }

Solution

Thank you very much for your answers. The solution I was searching for, is to use Platform.runLater(Runnable guiUpdater).

Best Answer

I would rewrite your SwingWorker as follows:

class PrimeNumbersTask extends Task<List<Integer>> {
    PrimeNumbersTask(TextArea textArea, int numbersToFind) {
        // initialize
    }

    @Override
    protected List<Integer> call() throws Exception {
        while (!enough && !isCancelled()) {
            number = nextPrimeNumber();
            updateMessage(Integer.toString(number));
            updateProgress(numbers.size(), numbersToFind);
        }
        return numbers;
    }
}

Usage:

TextArea textArea = new TextArea();
PrimeNumbersTask task = new PrimeNumbersTask(numbersToFind);
task.messageProperty().addListener((w, o, n)->textArea.appendText(n + "\n"));
new Thread(task).start(); // which would actually start task on a new thread 

Explanation:

Yes, we do not have a publish() method as the SwingWorker does in JavaFX, but in your case using the updateMessage() is sufficient, as we can register a listener to this property and append a new line every time the message is updated.

If this is not enough, you can always use Platform.runLater() to schedule GUI updates. If you are doing too many GUI updates and the GUI Thread is being slowed down, you can use the following idiom: Throttling javafx gui updates

Related Topic