使用我的Controller类,我必须执行多个IO命令(例如:SSH,带有一些参数值的RCP命令)顺序方式。每个命令都会有一些时间来执行。
我必须在每个命令开始执行时更新UI控制器。 然后,根据执行结果(无论成功还是失败),我必须再次更新UI。 然后必须使用相同的步骤执行下一个命令。
每个命令的执行取决于先前命令的结果。例如,
for (IOCommand command : commandsList) {
// Update the UI before start the command execution
messageTextArea.append("Command " + command.getType() + " Stated");
boolean result = commandExecutor(command);
if(result) {
// Update the UI after successful execution
messageTextArea.append("Command " + command.getType() + " Successfully Executed");
// Then go to next command execution
} else {
// Update the UI after failure execution
messageTextArea.append("Command " + command.getType() + " Failed");
// Fix the issue and do re execution
commandReExecutor(command);
}
}
为了完成这个逐步的UI更新,我必须使用一些与JavaFX相关的任务或服务相关的功能(否则它将挂起应用程序,直到完成所有命令的执行,并且它将同时更新UI)。但是由于性质或并发性,我不能在Task或Service的帮助下以顺序方式执行这些命令(不是一次又一次,一个接一个)。我该如何解决这个问题。提前致谢。
答案 0 :(得分:1)
我是项目中的确切要求,可以通过任务和服务来完成。你只需要一个正确的实施
几点注意:
1.始终使用service或Platform.runLater启动后台任务
2.如果要更新UI,必须从任务或服务完成
3.将任务的进度属性绑定到进度条的进度属性以进行平滑更新
4.类似地将Label的text属性绑定到任务的message属性,以平滑更新状态或其他内容
要执行像shell这样的外部命令,我已经写了下面的课:
package utils;
import controller.ProgressController;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.concurrent.Task;
import main.Installer;
public class ProcessExecutor extends Task<Integer>
{
Logger logger =Logger.getLogger("ProcessExecutor");
File dir;
String []cmd;
String cmds;
int exitCode=-1;
boolean NextStepExists=false;
Task nextStep;
public ProcessExecutor(String...cmd )
{
this.cmd=cmd;
this.dir=new File(System.getProperty("user.dir"));
this.nextStep=null;
NextStepExists=false;
}
public ProcessExecutor(Task nextStep,String...cmd )
{
this.cmd=cmd;
this.dir=new File(System.getProperty("user.dir"));
this.nextStep=nextStep;
NextStepExists=true;
}
public ProcessExecutor(Task nextStep,File dir,String...cmd)
{
this.cmd=cmd;
this.dir=dir;
this.nextStep=nextStep;
NextStepExists=true;
}
@Override
protected final Integer call()
{
cmds=new String();
for(String i:cmd)
cmds+=i+" "; // just to log cmd array
try
{
logger.info("Starting new process with cmd > "+cmds);
ProcessBuilder processBuilder=new ProcessBuilder(cmd);
processBuilder.directory(dir);
processBuilder.redirectErrorStream(true);
Map<String, String> env = processBuilder.environment();
// create custom environment
env.put("JAVA_HOME", "/opt/jdk1.7.0_45/");
Process pr=processBuilder.start();
BufferedReader in = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = in.readLine();
while (line != null) {
logger.log(Level.FINE,line);
ProgressController.instance.printToConsole(line);
line = in.readLine();
}
BufferedReader er = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
String erLine = in.readLine();
while (erLine != null) {
logger.log(Level.FINE,erLine);
ProgressController.instance.printToConsole(erLine);
erLine = in.readLine();
}
exitCode=pr.waitFor();
exitCode=pr.exitValue();
logger.info("Exit Value="+exitCode);
updateMessage("Completed Process");
if(exitCode!=0 && exitCode!=1)
{
logger.info("Failed to execute process commands >"+cmds+" with exit code="+exitCode);
failed();
}
else
{
logger.info("PE succeeded()");
if(NextStepExists)
Installer.pool.submit(nextStep);
succeeded();
}
}
catch(Exception e)
{
logger.log(Level.SEVERE,"Exception: Failed to execute process commands >"+cmds,e);
updateMessage(e.getMessage());
}
return new Integer(exitCode);
}
@Override
public void failed()
{
super.failed();
logger.log(Level.SEVERE,"Failed to execute process commands >"+cmds+"; ExitCode="+exitCode);
}
}
该类使用ProcessBuilder为新进程创建所需的环境,
它等待使用process.waitFor()完成进程的执行,可以使用processBuilder.directory(dir)设置进程目录。
为了执行单个任务&lt;&gt; ;在任何时候,都使用java.util.concurrent.ExecutorService
public ExecutorService pool=Executors.newSingleThreadExecutor();
pool.submit(new ProcessExecutor("installTomcat.bat","tomcat7"));
pool.submit(new ProcessExecutor("installPostgres.bat","postgresql","5432"));
通过这种方式,您可以一个接一个地执行批处理文件。
Executors.newSingleThreadExecutor()负责随时执行单个任务并对新提交的任务进行排队。
我&#39;我写了一个顺序执行的通用工作例子:
github
这是一个NetBeans JavaFX项目,它是一个广义的&amp;剥离了项目的版本。
希望这有帮助