在后台线程中运行服务

时间:2018-05-16 15:34:15

标签: multithreading javafx service task background-thread

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

我想从数据库加载数据,在加载数据期间,我希望进度条指示进度。首先,我创建了任务,在后台线程中运行它,然后根据此任务更新进度条。但是,我发现这个任务不可重复使用,所以下次按下按钮时,它无法正常工作。稍后,我说服务可以多次运行任务,所以我已经将这些任务封装在服务中。

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

如何达到预期效果?

1 个答案:

答案 0 :(得分:0)

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

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

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

这是我发现的。看起来服务自动在后台线程上运行它的任务。我已经建了一个沙箱"我正在玩服务和进度条的程序。该程序包括进度条,两个文本字段,上面有两个按钮。第一个按钮可以启动service_countTo100,第二个按钮可以运行service_getActualCount。

现在在fxml文件中我设置进度条以确定默认状态。按下按钮1后,计数开始(显示在text_field1中),进度条根据实际进度发生变化。按下button2后,计数的实际值显示在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级。在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文件中定义的默认状态,这是不确定的。

结论:服务类创建在其中定义的任务,在任务完成后,任务不再存在,因此,没有进度与进度条绑定。< / p>

即使任务不再存在,也无法使用setProgress(double double)方法设置有界进度条的进度。你首先需要解开它。

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

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