运行 后台线程中的服务
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 前进。计数完成后,进度条再次设置为不确定状态,等待再次开始。
我可以运行在后台线程中服务吗?
我想从数据库加载数据,在加载数据期间我希望进度条指示进度。首先我创建了任务,运行 它在后台线程中,然后根据这个任务更新进度条。但是,我发现这个任务不可重用,所以下次我按下按钮时,它不起作用。后来发现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 前进。计数完成后,进度条再次设置为不确定状态,等待再次开始。