使用JavaFX Platform.runLater并从不同的线程访问UI
我有一些关于Platform.runLater
问题。 我有一个JavaFX Application类。 在这个类中,我运行一个线程(该线程从网络套接字读取数据)。
现在当我在线程中创建一个新的Stage
,系统会抛出一个execption(JavaFX事件调度程序线程和我的netork-read线程不一样) – 我理解这种行为。
但另一方面是,我将文本从网络阅读器附加到现有的TextArea
或添加/删除ListView
中的一些项目 – 这不会引发exception – 为什么? 我认为JavaFX是单线程的(ui库部分)。 这与Swing中的相同:有时它有效,有时你只有垃圾(因为EDT)?
我的问题:
- JavaFX事件调度程序线程何时抛出exception,何时抛出exception?
- 有关于此的任何好文件吗?
- 是否有更简单(更简洁和更清晰)的方式将
Platform.runLater
与run()
方法一起使用? 结合try catch(或多次捕获),它看起来很奇怪
我知道在一个线程中使用Platform.runLater
并不是那么好(设计解决方案)
“这不会例外 – 为什么?” 因为并非所有这些情况都是正确的……可能,由于性能方面的考虑,可能只是一个错过的function。
所有与JavaFX对象的交互(包括创建)必须在JFX线程上完成,如果要从另一个线程访问这些JFX对象 – 使用runLater或runAndWait方法。 如果它现在不抛出exception,它可能会在将来开始抛出exception。 与JFX对象的任何交互都可能导致后续操作和事件,这将由某些线程检查程序进行操作 – 您无法确定。
我不认为,这方面有任何好的文档 – 只是一个简单的规则 – 使用runLater或runAndWait。
更短更清洁的方式 – 将使用Lambda在JDK 8中提供。
亚历山大的答案捕获了关于你的问题的最重要的观点。
这个答案提供了一些补充信息。
JavaFX事件调度程序线程何时抛出exception,何时抛出exception?
JavaFX系统并不总是检查对影响活动场景图的对象的访问是否适当地限制在JavaFX线程中。 最终,确保这样的线程安全是JavaFX应用程序员的责任 – 而不是JavaFX系统。 在JavaFX中执行multithreading编程时必须非常小心,否则应用程序行为可能会失败或变得不可预测。
有关于此的任何好文件吗?
试试JavaFX教程: JavaFX中的并发 。
是否有更简单(更简洁和更清晰)的方式将Platform.runLater与run()方法一起使用?
不, Platform.runLater
非常简单。
作为旁白 。 。 。
任务和服务
考虑使用Worker的Task或Service子类。 这些是FutureTask的 JavaFX包装器(后者又是Runnable )。 Workers提供了一种调用方法来在后台线程上运行逻辑。 它们维护执行状态 (通过线程安全回调通知JavaFX线程以进行状态更改)并通过值 , 消息和exception属性返回调用结果。
利用Task
和Service
javadoc示例中的设计模式,通过以下function简化线程安全应用程序的创建:
- 用于UI更新的异步数据提取。
- 任务进度的定期消息更新。
- 构造尚未附加到显示场景的节点图。
- 通过进度条等监控进度
Worker
是Platform.runLater
补充。 在执行JavaFX应用程序线程并且希望在JavaFX应用程序线程上运行某些逻辑时,请使用Platform.runLater
。 在JavaFX应用程序线程上运行时使用Worker
,并希望在新线程上生成一些逻辑或(特别是)I / O,这样就不会阻止JavaFX应用程序线程。 你永远不会想在Platform.runLater
的run
方法中做网络I / O,但是经常想在Worker
的call
方法中做。
此外,使用Task
和Service
与使用Platform.runLater
不兼容。 例如,如果您有一个非常长的运行Task
,您希望定期将部分结果返回到UI或缓冲区填充,那么在任务的call
方法中执行Platform.runLater
就是这样做的方法。
当您没有库提供的现有线程服务时,工作人员很有用,而是创建自己的线程以在后台执行。 如果您有现有的线程服务,那么您将需要使用Platform.runLater
在JavaFX应用程序线程上执行逻辑。
请注意,即使您使用Worker
,您仍需要知道自己在做什么。 您仍然必须注意不要违反标准的JavaFX并发规则,例如永远不更新活动场景图上的节点(包括不更新活动场景图中的节点绑定的值 – 例如可观察的项目列表支持一个ListView )。