JavaFX:可以从非UI线程安全地操纵节点的变形吗? [英] JavaFX: Can a node's tranforms be safely manipulated from a non-UI thread?

查看:123
本文介绍了JavaFX:可以从非UI线程安全地操纵节点的变形吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用Javafx开发机器人模拟器.它使用单独的线程来计算每次增加时间后机器人及其各个零件应位于的位置. UI的实际更新是通过调用Platform.runLater()来处理的.

下面是一个如何处理名为leftFinger的节点(在本例中为Rectangle)的示例:

首先,在Controller类中,创建一个Translate对象并将其添加到节点的转换中:

leftFingerTranslateTransform = new Translate(0, 0);
leftFinger.getTransforms().add(leftFingerTranslateTransform);

然后,在传递给Platform.runLater()的方法中执行以下操作:

leftFingerTranslateTransform.setY(-40.0 * (armScale - 1.0));
leftFingerTranslateTransform.setX(fingerPos);

上面的方法效果很好.

有一次,我不小心将一些此节点重定位代码(即,对Tranlate.setX()Translate.setY()的调用)放到了非UI线程调用的方法中,而没有对.令我惊讶的是,这没有问题.但是我想知道这是否会引起问题.

我对有关javafx和多线程的信息的搜索使我相信,不能(或至少不应该)从非UI线程直接操纵UI.通过实验,我发现尝试从非UI线程向场景中添加节点会引发异常,但操作(即更改其属性)属于节点的转换不会.

我的问题是:可以安全地将属于节点 的转换的属性从非UI线程更改(不使用Platform.runLater())吗?

解决方案

在非UI线程上更改节点上的转换,当节点连接到活动场景时,可能会导致以下问题作为比赛条件.

不要这样做.

说明

从Wikipedia上的比赛条件:

当应用程序依赖于进程或线程的顺序或时间以使其正常运行时,种族条件就会在软件中出现.与电子设备一样,在某些重要的竞争条件下会导致无效的执行和错误.当进程或线程依赖某些共享状态时,通常会发生关键的竞争条件.对共享状态的操作是必须相互排斥的关键部分.不遵守此规则会打开破坏共享状态的可能性.

在这里,共享状态是从它们派生的变换和内容(例如场景的布局)的列表.

来自节点Javadoc ,已链接由Slaw发表评论:

节点对象可以在任何线程上构造和修改,只要它们尚未附加到正在显示的窗口中的场景即可.应用程序必须将节点附加到此类场景,或在JavaFX Application Thread上对其进行修改

之所以不安全,是因为JavaFX UI线程在定时脉冲上运行(请参见 解决方案

Changing transforms on the node from a non-UI thread, when the node is attached to an active scene, could cause issues such as race conditions.

Don’t do it.

Explanation

From Wikipedia on race conditions:

Race conditions arise in software when an application depends on the sequence or timing of processes or threads for it to operate properly. As with electronics, there are critical race conditions that result in invalid execution and bugs. Critical race conditions often happen when the processes or threads depend on some shared state. Operations upon shared states are critical sections that must be mutually exclusive. Failure to obey this rule opens up the possibility of corrupting the shared state.

Here, the shared state is the list of transforms and stuff which is derived from them (such as the layout of the scene).

From the Node Javadoc, as linked by Slaw in comments:

Node objects may be constructed and modified on any thread as long they are not yet attached to a Scene in a Window that is showing. An application must attach nodes to such a Scene or modify them on the JavaFX Application Thread

The reason that it is unsafe is because the JavaFX UI thread runs on a timed pulse (see the JavaFX architecture doc to understand this), concurrently to any non-UI threads. During the timed pulse, the scene is rendered, CSS is applied, transforms are applied, animated properties are updated, etc. So if you modify the transforms on a non-UI thread while they are being applied during the pulse processing by the UI thread, you have a potential race condition, which can result in corrupted shared state, and the outcome is unpredictable and possibly quite undesirable.

这篇关于JavaFX:可以从非UI线程安全地操纵节点的变形吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆