有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

绑定StringProperty时发生java多线程错误

我有一个关于多线程和StringProperty绑定的问题

我有一个类CacheManager,它包含一个Thread,它用服务器上的更改更新我的缓存。现在,我想用文本和进度百分比通知用户(在JavaFX中是LabelProgressBar)。为此,我使用公共静态DoublePropertyStringProperty,它们在CacheManager类中定义。我只是这样绑着它:

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抛出了一个错误?考虑多线程时,它们之间的区别是什么

任何关于重新设计的想法都是欢迎的,任何帮助都是非常感谢的


共 (1) 个答案

  1. # 1 楼答案

    调用导致从FX应用程序线程以外的线程更改UI的代码是错误的,,无论它是否引发异常。如果违反此规则,FX toolkit会尽最大努力抛出异常,但在某些情况下,对性能的影响太大,无法执行检查。如果创建这些绑定,那么对绑定到的属性的任何后续更改都必须在FX应用程序线程上执行。也就是说,如果你在后台线程中运行,你必须用如下代码更改属性:

    Platform.runLater(() -> CacheManager.progress.set(...));
    

    Platform.runLater(() -> CacheManager.status.set(...));
    

    因为您可能不希望您的服务代码绑定到JavaFX(通过^ {CD1>}类),您可以考虑使用侦听器而不是绑定,并从监听器中调度更新:

    CacheManager.progress.addListener((obs, oldValue, newValue) -> 
        Platform.runLater(() -> progressBar.setProgress(newValue.doubleValue())));
    CacheManager.status.addListener((obs, oldStatus, newStatus) -> 
        Platform.runLater(() -> someLabel.setText(newStatus)));
    

    如果用这些监听器替换绑定,则可以自由更新任何线程上的属性