Reputation: 65
I'm programming in javafx java 1.7, and i need help with a thread problem. All i need is for my program to write out "Pinging", while it gets the IP of the device and pings it. The problem is, that if i put both in a thread than only the first executes. If I only put one of them in a thread, than the one not in the thread executes. Any idea on how to run the first thread than do the second? Or any other way to geth the "Pinging" text to the Ping Label written out, while the program gets the ip and pings it?
@FXML
private void ciscoButton(ActionEvent event) throws IOException {
CiscoPing.setWrapText(true);
Task<Void> task1 = new Task<Void>() {
@Override public Void call() throws IOException {
String text1;
text1 = "Pinging";
Ping.setWrapText(true);
Ping.setText(text1);
return null;
}
};
new Thread(task1).start();
Task<Void> task = new Task<Void>() {
@Override public Void call() throws IOException {
String text2 = PingIp.PingEtherAddr(GetIp.retIpEther()).toString();
text2 = text2.substring(1, (text2.length() - 1));
Ping.setWrapText(true);
Ping.setText(text2);
return null;
}
};
new Thread(task).start();
}
Thank you for your time :) PS: yes this is the first time i tried using threads and I have been trying for 3-4 days now...
Upvotes: 0
Views: 99
Reputation: 209704
This is all well covered elsewhere on SO, but... The two most important things to know about threading in a JavaFX application are:
The Task
class is an implementation of Runnable
(so it can be passed to Thread
s) that provides various hooks for updating the UI on the FX Application thread. The Javadocs have copious clear examples.
In your particular case, the first Task
is redundant. The only thing it does is update the UI (so it must not be performed in a background thread), and there is no code in there that takes a long time to execute. So this should be performed directly in the FX Application Thread.
The second Task
performs a long-running call to find a String
, and that String
is used to update the UI. So this should be declared as a Task<String>
whose call method returns the String
. An onSucceeded
handler can be used to update the UI when the call is complete:
@FXML
private void ciscoButton(ActionEvent event) throws IOException {
CiscoPing.setWrapText(true);
String text1;
text1 = "Pinging";
Ping.setWrapText(true);
Ping.setText(text1);
final Task<String> task = new Task<String>() {
@Override
public String call() throws IOException {
String text2 = PingIp.PingEtherAddr(GetIp.retIpEther()).toString();
return text2.substring(1, (text2.length() - 1));
}
};
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent event) {
Ping.setWrapText(true);
String text = task.getValue(); // value returned from call()
Ping.setText(text);
}
});
new Thread(task).start();
}
Upvotes: 1
Reputation: 65
I finally found a solution, which does solve what i want, but it won't make it a multi thread code.
@FXML
private void Button(ActionEvent event) throws IOException {
Ping.setWrapText(true);
Task<Void> task2 = new Task<Void>() {
@Override
public Void call() throws IOException {
updateMessage("Pinging");
PingIp.PingIp(GetIp.retIp()).toString();
text2 = text2.substring(1, (text2.length() - 1));
updateMessage(text2);
return null;
}
};
Ping.textProperty().bind(task2.messageProperty());
new Thread(task2).start();
}
Thanks for the help, though ^^ The Libk that was posted as a "possible duplicate" gave me the idea to experiment with this.
Upvotes: 1