Verwendung von JavaFX Platform.runLater und Zugriff auf UI von einem anderen Thread

8

Ich habe ein paar Fragen zu Platform.runLater . Ich habe eine JavaFX-Anwendungsklasse. In dieser Klasse führe ich einen Thread aus (Der Thread liest Daten von einem Netzwerk-Socket).

Wenn ich jetzt ein neues Stage innerhalb des Threads anlege, gibt das System eine Ausnahme aus (JavaFX Event-Dispatcher-Thread und mein Netzwerk-Lese-Thread sind nicht identisch) - ich verstehe dieses Verhalten.

Aber die andere Seite ist, ich füge den Text vom Netzwerkleser an ein existierendes TextArea an oder füge einige Elemente in einem ListView<String> hinzu oder entferne - das wirft keine Ausnahme - warum? Ich dachte, dass JavaFX ein Singlethread ist (Der ui-Bibliotheksteil). Ist das das Gleiche wie in Swing: Manchmal klappt es und manchmal hast du einfach Müll (; wegen EDT)?

Meine Fragen:

  • Wann löst der JavaFX Event-Dispatcher-Thread eine Ausnahme aus und wann nicht?
  • Sind irgendwelche guten Dokumente dazu
  • Gibt es einen einfacheren (kürzeren und saubereren) Weg, Platform.runLater mit einer run() -Methode zu verwenden? In Kombination mit einem try catch (oder multiple catch) sieht es sehr seltsam aus

Ich weiß, dass die Verwendung von Platform.runLater in einem Thread nicht so gut ist (Design-Lösung)

    
swaechter 01.03.2013, 14:43
quelle

2 Antworten

10

"das wirft keine Ausnahme - warum?" weil nicht alle solchen Fälle geholt werden ... Möglicherweise, wegen der Leistungsüberlegungen, möglicherweise, ist es nur eine verpasste Funktionalität.

Alle Interaktionen mit JavaFX-Objekten (einschließlich der Erstellung) müssen im JFX-Thread ausgeführt werden. Wenn Sie auf diese JFX-Objekte von einem anderen Thread aus zugreifen möchten, verwenden Sie die Methoden runLater oder runAndWait. Wenn es jetzt keine Ausnahme auslöst, wird es möglicherweise in Zukunft Ausnahmen auslösen. Jede Interaktion mit dem JFX-Objekt kann zu Folgeaktionen und -ereignissen führen, die von einem Thread-Checker übernommen werden - Sie können nicht sicher sein.

Ich glaube nicht, dass es eine gute Dokumentation darüber gibt - nur eine einfache Regel - benutze runLater oder runAndWait.

Kürzere und sauberere Methode - wird in JDK 8 mit Lambda bereitgestellt.

    
Alexander Kirov 01.03.2013, 15:07
quelle
15

Alexanders Antwort fängt die wichtigsten Punkte bezüglich Ihrer Fragen ein.

Diese Antwort enthält einige zusätzliche Informationen.

  

Wann löst der JavaFX-Event-Dispatcher-Thread eine Ausnahme aus und wann nicht?

Das JavaFX-System prüft nicht immer, ob Zugriffe auf Objekte, die das aktive Szenegraph beeinflussen, ordnungsgemäß auf den JavaFX-Thread beschränkt sind. Letztlich liegt die Verantwortung für die Thread-Sicherheit beim JavaFX-Anwendungsprogrammierer - nicht beim JavaFX-System. Sie müssen sehr vorsichtig sein, wenn Sie Multi-Threaded-Programmierung in JavaFX durchführen, andernfalls kann das Verhalten der Anwendung fehlschlagen oder unvorhersehbar werden.

  

Sind irgendwelche guten Dokumente darüber

Probieren Sie das JavaFX-Tutorial: Parallelität in JavaFX .

  

Gibt es einen einfacheren (kürzeren und saubereren) Weg, Platform.runLater mit einer run () Methode zu benutzen?

Nein. Platform.runLater ist so einfach wie es geht.

Als beiseite. . .

Aufgabe und Service

Erwägen Sie, die Aufgabe oder Service Unterklassen von Arbeiter . Dies sind JavaFX-Wrapper für FutureTask (was wiederum ein Runnable ). Die Mitarbeiter stellen eine Aufruf -Methode bereit, um die Logik auf einem auszuführen Hintergrundfaden. Sie behalten die Ausführung Status bei (mit Thread-sicherer Callback-Benachrichtigung für den JavaFX-Thread für Statusänderungen) und gibt die Ergebnisse des Aufrufs über value , Nachricht und Ausnahme Eigenschaften.

Nutzen Sie die Entwurfsmuster in den Beispielen Task und Service javadoc, um die Erstellung threadsicherer Anwendungen mit Funktionen wie:

zu vereinfachen
  • Asynchrones Abrufen von Daten für die UI-Aktualisierung.
  • Periodische Nachrichtenaktualisierungen für den Aufgabenfortschritt.
  • Erstellen von Knotendiagrammen, die noch nicht an eine angezeigte Szene angehängt sind.
  • Überwachung des Fortschritts über Fortschrittsbalken usw.

A Worker ist komplementär zu Platform.runLater . Verwenden Sie Platform.runLater , wenn Sie den JavaFX-Anwendungs-Thread ausführen und eine Logik für den JavaFX-Anwendungs-Thread ausführen möchten. Verwenden Sie Worker , wenn Sie den JavaFX-Anwendungs-Thread ausführen und eine Logik oder (insbesondere) E / A in einem neuen Thread generieren möchten, damit Sie den JavaFX-Anwendungs-Thread nicht blockieren. Sie würden niemals Netzwerk-I / O in der Platform.runLater -Methode von run durchführen wollen, aber oft möchten Sie dies in% Worker -Methode tun.

Auch die Verwendung von call und Task ist nicht inkompatibel mit der Verwendung von Service . Wenn Sie zum Beispiel sehr lange Platform.runLater ausführen, von denen Sie regelmäßig Teilergebnisse an die Benutzeroberfläche zurückgeben möchten oder wenn ein Puffer gefüllt ist, können Sie Task in der Methode Platform.runLater der Aufgabe ausführen.

Workers sind hilfreich, wenn Sie nicht über einen vorhandenen Thread-Dienst verfügen, der von einer Bibliothek bereitgestellt wird, sondern stattdessen eigene Threads erstellen, die im Hintergrund ausgeführt werden. Wenn Sie einen vorhandenen Thread-Dienst haben, müssen Sie call verwenden, um Logik für den JavaFX-Anwendungsthread auszuführen.

Beachten Sie, dass Sie immer noch wissen müssen, was Sie tun, auch wenn Sie Platform.runLater verwenden. Sie müssen dennoch darauf achten, dass Sie nicht die standardmäßigen JavaFX-Regeln für den gemeinsamen Zugriff verletzen, z. B. niemals Knoten im aktiven Szenendiagramm aktualisieren (einschließlich der Aktualisierung von Werten, an die Knoten im aktiven Szenegraph gebunden sind). Beispiele sind die beobachtbare Liste von Elemente , die ein ListView ).

    
jewelsea 02.03.2013 01:00
quelle