Uso de JavaFX Platform.runLater y acceso a UI desde un hilo diferente

Tengo algunas preguntas sobre Platform.runLater . Tengo una clase de aplicación JavaFX. En esta clase, ejecuto un hilo (El hilo lee datos de un socket de red).

Ahora cuando creo un nuevo Stage dentro del hilo, el sistema arroja una excepción (el hilo del despachador de eventos JavaFX y mi hilo netork-read no son los mismos). Entiendo este comportamiento.

Pero el otro lado es, agrego el texto del lector de red a un área de texto existente o agrego / elimino algunos elementos en un ListView – esto no arroja una excepción – ¿por qué? Pensé que JavaFX es singlethreaded (La parte de la biblioteca de ui). ¿Es esto lo mismo que en Swing: a veces funciona y a veces tienes basura (porque EDT)?

Mis preguntas:

  • ¿Cuándo lanza el thread del dispatcher de eventos JavaFX una excepción y cuándo no?
  • ¿Hay buenos documentos sobre esto?
  • ¿Existe alguna manera más fácil (más corta y más limpia) de utilizar Platform.runLater con un método run() ? En combinación con una captura de prueba (o captura múltiple), se ve muy extraño

Sé que el uso de Platform.runLater en un hilo no es tan bueno (solución de diseño)

“Esto no arroja una excepción, ¿por qué?” porque no todos estos casos se tienen en cuenta … Posiblemente, debido a consideraciones de rendimiento, posiblemente, es solo una funcionalidad perdida.

Todas las interacciones con objetos JavaFX (incluida la creación) deben realizarse en el hilo JFX, si desea acceder a esos objetos JFX desde otro hilo, use los métodos runLater o runAndWait. Si no lanza una excepción ahora, posiblemente comenzará a lanzar excepciones en el futuro. Cualquier interacción con un objeto JFX puede causar acciones y eventos posteriores, que serán evaluados por un inspector de hilos; no puede estar seguro.

No creo, hay una buena documentación sobre esto, solo una regla simple, use runLater o runAndWait.

Forma más corta y más limpia: se proporcionará en JDK 8 usando Lambda.

La respuesta de Alexander capta los puntos más importantes con respecto a sus preguntas.

Esta respuesta proporciona cierta información complementaria.

¿Cuándo lanza el thread del dispatcher de eventos JavaFX una excepción y cuándo no?

El sistema JavaFX no siempre verifica que los accesos a los objetos que afectan al gráfico de escena activo estén restringidos de forma adecuada al subproceso JavaFX. En última instancia, garantizar la seguridad de estos hilos es responsabilidad del progtwigdor de aplicaciones JavaFX, no del sistema JavaFX. Debe tener mucho cuidado al realizar la progtwigción de subprocesos múltiples en JavaFX, de lo contrario el comportamiento de la aplicación puede fallar o volverse impredecible.

¿Hay buenos documentos sobre esto?

Pruebe el tutorial de JavaFX: Concurrencia en JavaFX .

¿Existe alguna manera más fácil (más corta y más limpia) de utilizar Platform.runLater con un método run ()?

No. Platform.runLater es tan simple como se puede.


Como un aparte . . .

Tarea y servicio

Considere usar las subclases de Tarea o Servicio de Trabajador . Estos son envoltorios JavaFX para FutureTask (que a su vez es Runnable ). Los trabajadores proporcionan un método de llamada para ejecutar la lógica en un hilo de fondo. Mantienen el estado de ejecución (con notificación de callback segura a la hebra JavaFX para cambios de estado) y devuelven resultados de la llamada a través de propiedades de valor , mensaje y excepción .

Aproveche los patrones de diseño en los ejemplos de javadoc de Task y Service para simplificar la creación de aplicaciones seguras para subprocesos con funciones como:

  • Captura asincrónica de datos para la actualización de UI.
  • Actualizaciones periódicas de mensajes para el progreso de la tarea.
  • Construir gráficos de nodo que aún no están unidos a una escena mostrada.
  • Monitoreando el progreso a través de barras de progreso, etc.

Un Worker es complementario de Platform.runLater . Utilice Platform.runLater cuando esté ejecutando fuera del subproceso de la aplicación JavaFX y desee ejecutar un poco de lógica en el subproceso de la aplicación JavaFX. Use un Worker cuando esté ejecutando en el subproceso de la aplicación JavaFX y desee generar alguna lógica o (especialmente) E / S en un nuevo subproceso para que no bloquee el subproceso de la aplicación JavaFX. Nunca querría hacer E / S de red dentro del método de run Platform.runLater , pero a menudo querría hacerlo en un método de call Worker .

Además, el uso de Task y Service no es incompatible con el uso de Platform.runLater . Por ejemplo, si tiene una Task ejecución muy larga desde la cual desea devolver resultados parciales a la IU periódicamente o cuando se llena un búfer, ejecutar Platform.runLater en el método de call la tarea es la forma de hacerlo.

Los trabajadores son útiles cuando no tiene un servicio de subprocesamiento existente provisto por una biblioteca, sino que crean sus propios subprocesos para ejecutarlos en segundo plano. Si tiene un servicio de subprocesamiento existente, necesitará usar Platform.runLater para realizar la lógica en el subproceso de la aplicación JavaFX.

Tenga en cuenta que aún necesita saber lo que está haciendo, incluso si usa un Worker . También debe tener cuidado de no infringir las reglas de concurrencia JavaFX estándar, como no actualizar nunca los nodos en el gráfico de escena activo (incluso no actualizar los valores a los que están vinculados los nodos en el gráfico de escena activo, como la lista observable de elementos de respaldo). un ListView ).

    Intereting Posts