Platform.runLater y Tarea en JavaFX

Resuelto Marc Rasmussen asked hace 12 años • 4 respuestas

He estado investigando un poco sobre esto pero todavía estoy MUY confundido, por decir lo menos.

¿Alguien puede darme un ejemplo concreto de cuándo usar Tasky cuándo usar Platform.runLater(Runnable);? ¿Cuál es exactamente la diferencia? ¿Existe una regla de oro sobre cuándo utilizar alguno de estos?

Corríjame también si me equivoco, pero ¿no son estos dos "Objetos" una forma de crear otro hilo dentro del hilo principal en una GUI (utilizada para actualizar la GUI)?

Marc Rasmussen avatar Dec 09 '12 10:12 Marc Rasmussen
Aceptado

Úselo Platform.runLater(...)para operaciones rápidas y simples y Taskpara operaciones complejas y grandes.

  • Caso de uso paraPlatform.runLater(...)
  • Caso de uso para Task: Ejemplo de tarea en la aplicación Ensemble

Ejemplo: ¿Por qué no podemos usarlo Platform.runLater(...)para cálculos largos? (Tomado de la referencia siguiente).

Problema: hilo en segundo plano que solo cuenta de 0 a 1 millón y actualiza la barra de progreso en la interfaz de usuario.

Código usando Platform.runLater(...):

final ProgressBar bar = new ProgressBar();
new Thread(new Runnable() {
    @Override public void run() {
    for (int i = 1; i <= 1000000; i++) {
        final int counter = i;
        Platform.runLater(new Runnable() {
            @Override public void run() {
                bar.setProgress(counter / 1000000.0);
            }
        });
    }
}).start();

Este es un horrible trozo de código, un crimen contra la naturaleza (y la programación en general). Primero, perderás células cerebrales con solo mirar este doble anidamiento de Runnables. En segundo lugar, va a inundar la cola de eventos con pequeños Runnables; de hecho, un millón de ellos. Claramente, necesitábamos alguna API para facilitar la escritura de trabajadores en segundo plano que luego se comunican con la interfaz de usuario.

Código usando tarea:

Task task = new Task<Void>() {
    @Override public Void call() {
        static final int max = 1000000;
        for (int i = 1; i <= max; i++) {
            updateProgress(i, max);
        }
        return null;
    }
};

ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();

No sufre ninguno de los defectos exhibidos en el código anterior.

Referencia: subprocesamiento de trabajadores en JavaFX 2.0

invariant avatar Dec 09 '2012 23:12 invariant
  • Platform.runLater: Si necesita actualizar un componente de la GUI desde un hilo que no es GUI, puede usarlo para poner su actualización en una cola y será manejada por el hilo de la GUI lo antes posible.
  • Taskimplementa la Workerinterfaz que se utiliza cuando necesita ejecutar una tarea larga fuera del subproceso de la GUI (para evitar congelar su aplicación) pero aún necesita interactuar con la GUI en algún momento.

Si estás familiarizado con Swing, el primero equivale al concepto de SwingUtilities.invokeLatery el segundo al concepto de SwingWorker.

El javadoc de Task ofrece muchos ejemplos que deberían aclarar cómo se pueden utilizar. También puede consultar el tutorial sobre concurrencia .

assylias avatar Dec 09 '2012 08:12 assylias

Ahora se puede cambiar a la versión lambda.

@Override
public void actionPerformed(ActionEvent e) {
    Platform.runLater(() -> {
        try {
            //an event with a button maybe
            System.out.println("button is clicked");
        } catch (IOException | COSVisitorException ex) {
            Exceptions.printStackTrace(ex);
        }
    });
}
Cugomastik avatar Oct 17 '2014 10:10 Cugomastik

Una razón para utilizar un Platform.runLater() explícito podría ser que vinculó una propiedad en la interfaz de usuario a una propiedad de servicio (resultado). Entonces, si actualiza la propiedad del servicio vinculado, debe hacerlo mediante runLater():

En el hilo de la interfaz de usuario, también conocido como hilo de la aplicación JavaFX:

...    
listView.itemsProperty().bind(myListService.resultProperty());
...

en Implementación del servicio (trabajador en segundo plano):

...
Platform.runLater(() -> result.add("Element " + finalI));
...
Alexander Pietsch avatar Jul 17 '2015 09:07 Alexander Pietsch