运行 后台线程中的服务

Run Service in background Thread

我可以运行在后台线程中服务吗?

我想从数据库加载数据,在加载数据期间我希望进度条指示进度。首先我创建了任务,运行 它在后台线程中,然后根据这个任务更新进度条。但是,我发现这个任务不可重用,所以下次我按下按钮时,它不起作用。后来发现Service可以运行多次执行任务,所以我把那些任务封装在Service里面了。

现在效果很好 - 每次我点击按钮时,table 都会重新加载 - 除了进度条没有移动。

我怎样才能达到想要的结果?

好的...这是完整的代码:https://mega.nz/#!yUsjgJyZ!DHfuBqsujAHurS-pQ_W5y8BAflOtvxsm48goRPkDsxA

首先,我想告诉你我的目标是什么:

当我运行编程时,我希望进度条处于不确定状态。按下按钮后,我希望进度条反映服务的进度。完成服务后,我希望进度条完成(100%)。

这是我的发现。看起来服务自动 运行s 它是后台线程上的任务。我构建了一个 "sand box" 程序,我在其中使用服务和进度条。该程序由进度条、两个文本字段和上面的两个按钮组成。第一个按钮可以启动 service_countTo100,第二个按钮可以 运行 service_getActualCount。

现在在 fxml 文件中,我将进度条设置为不确定的默认状态。按下按钮 1 后,开始计数(显示在 text_field1 中),进度条根据实际进度发生变化。按下按钮2后,计数的实际值显示在text_field2中。这里出现了一些问题。为了演示这些问题,我将向您展示服务的源代码:

// Create the service
public static Service<Integer> serviceTo100 = new Service<Integer>() {
    @Override
    protected Task<Integer> createTask() {
        Task<Integer> taskTo100 = new Task<Integer>() {
            @Override protected Integer call() throws Exception {

                int iterations;
                updateProgress(-1, 100);
                for (iterations = 0; iterations < 100; iterations++) {
                    if (isCancelled()) {
                        updateMessage("Cancelled");
                        break;
                    }

                    updateMessage("Iteration " + iterations);
                    updateProgress(iterations, 100);

                    // Now block the thread for a short time, but be sure
                    // to check the interrupted exception for cancellation!
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException interrupted) {
                        if (isCancelled()) {
                            updateMessage("Cancelled");
                            break;
                        }
                    }
                }

            //udpateProgress(100, 100);    
            return iterations;
            }
        };
    return taskTo100;
    }
};

如您所见,有一个从 0 到 100 计数的简单循环,还有一个更新进度的 updateProgress(iterations, 100); 语句。此服务位于 Services class。在 FXMLDocumentController.java 中,名为 runService(Service service) 的方法定义如下:

public void runService(Service service){

        service.start();
        progressBar.progressProperty().bind(service.progressProperty());

        service.setOnSucceeded((event) -> {
            service.reset();
            progressBar.progressProperty().unbind();
            progressBar.setProgress(1);                                
        });
}

initialize 看起来像这样:

@Override
public void initialize(URL url, ResourceBundle rb) {
    btn_start1.setOnAction((event) -> {

        Service service = Services.serviceTo100;
        runService(service);
        txt_field1.textProperty().bind(service.messageProperty());                     
        System.out.printf("something\n");  

    });
    .
    .
    .
    }//end of initialize

现在最有趣的事情(至少对我这个新手来说)开始发挥作用了。

在服务定义中,您可以注意到注释行 //updateProgress(100,100)。那是我尝试在计数停止时将进度条设置为完成状态。但是 java 忽略了那一行。我试着输入 System.out.print("Something"); 并且成功了,但是 updateProgress(100, 100) 没有。计数完成后,进度条设置为其在 fxml 文件中定义的默认状态,这是不确定的。

结论:服务class创建了定义在其中的任务,任务完成后,任务不存在了,因此没有任何进展与进度条绑定

即使任务不存在,也无法使用setProgress(double double)方法设置限界进度条的进度。首先需要解除绑定。

现在我得到了我需要的东西:

你运行程序,进度条处于不确定状态,等待命中。您按下按钮,服务开始计数到 ​​100,并且进度条根据服务的 progressProperty 前进。计数完成后,进度条再次设置为不确定状态,等待再次开始。