使用JavaFX 8时,我们需要通过Platform.runLater
运行与GUI的交互,否则如果从另一个线程运行它们将抛出异常。
然而,Platform.runLater
的实现从不检查它当前是否在JavaFX线程上。
我写了以下方法:
public static void runSafe(final Runnable runnable) {
Objects.requireNonNull(runnable, "runnable");
if (Platform.isFxApplicationThread()) {
runnable.run();
}
else {
Platform.runLater(runnable);
}
}
这可确保它永远不会在非fx应用程序线程上运行。
是否有任何理由认为默认实现不会造成这种短路?
答案 0 :(得分:16)
runLater
实际上将您的Runnable放入队列中,以便在FX线程可用时执行。该方法可以通过非FX线程访问。想象一下,其他一些线程已将任务放在runLater
队列中,然后再次调用runLater
,无论是否来自FX线程,都应将新任务放在该队列的尾部。
通过短路,您建议先前的任务基本上具有较低的优先级,这可能是不可取的。
答案 1 :(得分:13)
在调用函数时,函数被调用' runLater',我希望它能在以后运行,而不是现在运行。
在我看来,实施是基于它的名称and it's documentation做正确的事情:
将来某个未指定的时间在JavaFX应用程序线程上运行指定的Runnable。
此方法可以从任何线程调用,将Runnable发布到事件队列,然后立即返回给调用者。 Runnables按照发布顺序执行。传递给runLater方法的runnable将在任何Runnable传递给后续的runLater调用之前执行
如果您不希望代码稍后运行,请不要让它稍后运行。这就是你基本上用你的代码完成的。
答案 2 :(得分:0)
我看到人们偶尔会在Swing的EDT中呼叫EventQueue.invokeLater
......根据佳能的说法,这是一种合法的技术。所以这与JavaFX中的情况相同,除非我错了。
invokeLater
,因为selectAll()
需要让所有当前的EDT事件在调用之前完成:此解决方案确实确保selectAll
不能在其他EDT代码发生之前运行。
但我保持这个答案有漏洞。看到我建议的答案(用Jython编写,但应该是可以理解的)。假设有人将“点击计数开始编辑”设置为1.假设,更谨慎的是,invokeLater
和selectAll
之间发生了不可预测的事情。除非你完全确定你没有替代机制,或者绝对确定两个线程的事件和对象完全“解耦”,否则我个人会说避免从JavaFX线程调用runLater
。
并发总是在等着你。因此,最好小心使用这种技术!