Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javafx 后台线程是否直接访问UI_Javafx - Fatal编程技术网

Javafx 后台线程是否直接访问UI

Javafx 后台线程是否直接访问UI,javafx,Javafx,这是我的代码,有人能解释为什么每次都能用吗 package dingding; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextField; i

这是我的代码,有人能解释为什么每次都能用吗

package dingding;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;


public class Dingding extends Application {

    TextField tfAuto = new TextField("0");
    AutoRunThread runner = new AutoRunThread();
    boolean shouldStop = false;

    private class AutoRunThread extends Thread {

        @Override
        public void run() {
            while (true) {
                int i = Integer.parseInt(tfAuto.getText());
                ++i;
                tfAuto.setText(String.valueOf(i));
                try {
                Thread.sleep(1000);
                } catch (Throwable t) {

                }
                if (shouldStop) {
                    runner = null;
                    shouldStop = false;
                    return;
                }
            }
        }
    }

    @Override
    public void start(Stage primaryStage) {

        Button btnStart = new Button("Increment Automatically");
        Button btnStop = new Button("Stop Autotask");

        btnStart.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if (runner == null) {
                    runner = new AutoRunThread();
                    runner.setDaemon(true);
                }
                if (runner != null && !(runner.isAlive())) {
                    runner.start();
                }
            }
        });

        btnStop.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                shouldStop = true;
            }
        });


        VBox rootBox = new VBox();
        HBox autoBox = new HBox();

        autoBox.getChildren().addAll(tfAuto, btnStart, btnStop);

        rootBox.getChildren().addAll(autoBox);

        Scene scene = new Scene(rootBox, 300, 250);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}
包顶顶;
导入javafx.application.application;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.TextField;
导入javafx.scene.layout.VBox;
导入javafx.scene.layout.HBox;
导入javafx.stage.stage;
公共类丁丁扩展应用{
TextField tfAuto=新的TextField(“0”);
AutoRunThread runner=新的AutoRunThread();
布尔值shouldStop=false;
私有类AutoRunThread扩展线程{
@凌驾
公开募捐{
while(true){
int i=Integer.parseInt(tfAuto.getText());
++一,;
tfAuto.setText(String.valueOf(i));
试一试{
睡眠(1000);
}捕获(可丢弃的t){
}
如果(应该停止){
runner=null;
shouldStop=false;
返回;
}
}
}
}
@凌驾
公共无效开始(阶段primaryStage){
按钮btnStart=新按钮(“自动递增”);
按钮btnStop=新按钮(“停止自动任务”);
btnStart.setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent事件){
if(runner==null){
runner=新的自动取消线程();
setDaemon(true);
}
if(runner!=null&&!(runner.isAlive()){
runner.start();
}
}
});
setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent事件){
shouldStop=true;
}
});
VBox rootBox=新的VBox();
HBox autoBox=新的HBox();
autoBox.getChildren().addAll(tfAuto、btnStart、btnStop);
rootBox.getChildren().addAll(autoBox);
场景=新场景(根盒,300250);
setTitle(“你好,世界!”);
初级阶段。场景(场景);
primaryStage.show();
}
/**
*@param指定命令行参数
*/
公共静态void main(字符串[]args){
发射(args);
}
}

正如我在评论中所说,不正确同步的代码本身并不能保证出错。然而,这并不意味着当在多线程环境中使用上述代码时,它实际上是在工作的——你只是幸运而已。最终,您将遇到未定义的行为,例如损坏的状态、陈旧的值和意外的异常。这是因为,在没有同步的情况下,一个线程执行的操作不能保证对任何其他线程可见。您需要一个before-before关系,更好地描述在java.util.concurrent和中

JavaFX和大多数UI框架/工具包一样,是单线程的。这意味着在本例中有一个特殊的线程,JavaFX应用程序线程-负责所有与UI相关的操作1。必须使用此线程(且仅此线程)访问和/或修改与“活动”场景图(即,在显示的窗口2中的场景中的节点)相关的状态。使用任何其他线程都可能导致上述未定义的行为

一些与UI相关的函数实际上确保在JavaFX应用程序线程上调用它们,如果没有,通常会抛出一个
IllegalStateException
。然而,其余的函数将允许您从任何线程调用它们,但这并不意味着这样做是安全的。我相信这是通过这种方式完成的,因为检查每个UI相关函数中的线程是维护的噩梦,并且会带来不小的性能成本


一,。这个稍微复杂一点,;JavaFX还有一个“prism渲染线程”和一个“媒体线程”。有关更多信息,请参阅。但请注意,从应用程序开发人员的角度来看,唯一重要的线程是JavaFX应用程序线程


二,。这是由以下人员记录的。请注意,一些节点,例如
WebView
,在线程方面限制更大;这将记录在适当的位置。

是的,您必须更新fx应用程序线程上作为场景图一部分的节点-无例外。反过来说:只要它还没有被添加,你就可以从任何线程中更改它是的@kleopatra这也是我所想的,我的问题是为什么它不起作用,如果它起作用,那是偶然的;)不太了解您的目的:您不能更改场景图中控件的任何属性。您可能会侥幸逃脱(并不是每个更改都能防止线程冲突),但这样做会创建不稳定的软件,注定会出现不可预测的故障,并且此类故障极难调试和修复。。那么你的观点是什么?别这样!不正确的同步代码本身并不保证出错,但这并不意味着在多线程环境中,代码“正常工作”——你只是运气好而已。当谈到JavaFX时,实际上只有一些与UI相关的函数进行检查,以确保FX线程正在调用它。其余的函数允许您从任何线程以静默方式调用它们,但这样做可能会导致未定义的行为(例如损坏的状态、意外的异常、过时的值等)。