绑定 StringProperty 时出现多线程错误
Multi-Threading error when binding a StringProperty
我有一个关于多线程和 StringProperty 绑定的问题。
我有一个 class CacheManager
,其中包含一个 Thread
,它使用服务器上的更改更新我的缓存。现在,我想用文本和进度百分比通知用户(在 JavaFX 中是 Label
和 ProgressBar
)。为此,我使用 public static DoubleProperty
和 StringProperty
,它们在 CacheManager
class 中定义。我只是这样绑定它:
progressBar.progressProperty().bind(CacheManager.progress);
someLabel.textProperty().bind(CacheManager.status);
现在,在更新程序线程中,我更新了这些 Properties
。使用 DoubleProperty
这工作得很好,并且 ProgressBar
完美地显示了进度。但是,使用状态(来自 StringProperty
的文本)更新 Label
会引发错误:java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-9
现在,我的问题是:为什么 DoubleProperty
工作得很好,而 StringProperty
却抛出错误?考虑到多线程,它们之间有什么区别?
也欢迎任何关于重新设计的想法,非常感谢任何帮助!
从 FX 应用程序线程以外的线程调用导致 UI 更改的代码是错误的,无论它是否抛出异常.如果违反此规则,FX 工具包会尽最大努力抛出异常,但在某些情况下,对性能的影响太大而无法执行检查。如果您创建这些绑定,那么您绑定的属性的任何后续更改 必须 在 FX 应用程序线程上执行。即,如果您 运行 在后台线程中,您 必须 使用如下代码更改属性:
Platform.runLater(() -> CacheManager.progress.set(...));
和
Platform.runLater(() -> CacheManager.status.set(...));
由于您可能不希望您的服务代码绑定到 JavaFX(通过 Platform
class),您可以考虑使用侦听器而不是绑定,并从听众:
CacheManager.progress.addListener((obs, oldValue, newValue) ->
Platform.runLater(() -> progressBar.setProgress(newValue.doubleValue())));
CacheManager.status.addListener((obs, oldStatus, newStatus) ->
Platform.runLater(() -> someLabel.setText(newStatus)));
如果您用这些侦听器替换绑定,那么您可以自由地更新任何线程上的属性。
我有一个关于多线程和 StringProperty 绑定的问题。
我有一个 class CacheManager
,其中包含一个 Thread
,它使用服务器上的更改更新我的缓存。现在,我想用文本和进度百分比通知用户(在 JavaFX 中是 Label
和 ProgressBar
)。为此,我使用 public static DoubleProperty
和 StringProperty
,它们在 CacheManager
class 中定义。我只是这样绑定它:
progressBar.progressProperty().bind(CacheManager.progress);
someLabel.textProperty().bind(CacheManager.status);
现在,在更新程序线程中,我更新了这些 Properties
。使用 DoubleProperty
这工作得很好,并且 ProgressBar
完美地显示了进度。但是,使用状态(来自 StringProperty
的文本)更新 Label
会引发错误:java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-9
现在,我的问题是:为什么 DoubleProperty
工作得很好,而 StringProperty
却抛出错误?考虑到多线程,它们之间有什么区别?
也欢迎任何关于重新设计的想法,非常感谢任何帮助!
从 FX 应用程序线程以外的线程调用导致 UI 更改的代码是错误的,无论它是否抛出异常.如果违反此规则,FX 工具包会尽最大努力抛出异常,但在某些情况下,对性能的影响太大而无法执行检查。如果您创建这些绑定,那么您绑定的属性的任何后续更改 必须 在 FX 应用程序线程上执行。即,如果您 运行 在后台线程中,您 必须 使用如下代码更改属性:
Platform.runLater(() -> CacheManager.progress.set(...));
和
Platform.runLater(() -> CacheManager.status.set(...));
由于您可能不希望您的服务代码绑定到 JavaFX(通过 Platform
class),您可以考虑使用侦听器而不是绑定,并从听众:
CacheManager.progress.addListener((obs, oldValue, newValue) ->
Platform.runLater(() -> progressBar.setProgress(newValue.doubleValue())));
CacheManager.status.addListener((obs, oldStatus, newStatus) ->
Platform.runLater(() -> someLabel.setText(newStatus)));
如果您用这些侦听器替换绑定,那么您可以自由地更新任何线程上的属性。