JavaFX - 如何在退出应用程序之前关闭所有 运行 线程?
JavaFX - How to close all running Threads before exiting the Application?
我使用 JavaFX 创建了一个 Client/Server 聊天应用程序。当 'Start Server'-Button 被按下时,我的 ServerController 创建了一个服务器对象,它在一个单独的线程上 运行ning。
这是我的问题:
每当我用默认的 'x'-Button 关闭 Window 时,服务器线程就会终止,但不会通知活动客户端服务器已终止。我需要通知客户服务器已关闭,就像我使用 'Stop-Server'-Button 所做的那样。我的服务器持有对控制器对象的引用。
public class ServerController {
@FXML
TextArea chatEvent_txt;
@FXML
Button start_btn;
@FXML
Button stop_btn;
private Server server;
private boolean started = false;
private StringBuffer chatEvents = new StringBuffer("");
/**
* @param e
*/
@FXML
public void startButtonAction(ActionEvent e) {
if (!started) {
this.server = new Server(this);
new Thread(server).start();
started = true;
chatEvents = chatEvents.append("Server started.." + "\n");
chatEvent_txt.setText(chatEvents.toString());
} else {
chatEvent_txt.setText("Server already started\n");
}
}
这是我的 'Stop-Server'- 通知所有客户端的按钮,服务器将关闭,然后关闭所有套接字和类似的东西。
@FXML
public void stopButtonAction(ActionEvent e) {
if (started) {
server.setRunning(false);
chatEvent_txt.setText("Server wurde gestoppt\n");
started = false;
}
}
方法setRunning();只会将一个变量设置为 false,这样线程就会离开接受新客户端的 while 循环。当 while 循环结束时,服务器将向所有客户端发送一条消息,以便他们知道服务器将关闭。
运行-我服务器上的方法:
@Override
public void run() {
try {
serverSocket.setSoTimeout(500);
while (running) {
try {
clientSocket = serverSocket.accept();
new Thread(new Listener(clientSocket, this)).start();
} catch (IOException e) {
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
try {
broadcastMessage(new Message(Message.Type.DISCONNECT_OK, "Server"));
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
如何让 'x'-Button 与 "Stop Server"-Button 执行相同的操作?
重构为
@FXML
public void stopButtonAction(ActionEvent e) {
shutdown();
}
public void shutdown() {
if (started) {
server.setRunning(false);
chatEvent_txt.setText("Server wurde gestoppt\n");
started = false;
}
}
然后当您加载并显示 FXML 时,您可以:
FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
someStage.setScene(scene);
ServerController controller = loader.getController();
someStage.setOnCloseRequest(e -> controller.shutdown());
如果您需要 window 在按下关闭按钮时不关闭(例如,如果您需要在以编程方式关闭 window 之前等待一切正常关闭),您可以调用 e.consume()
在 onCloseRequest
处理程序中。
我使用 JavaFX 创建了一个 Client/Server 聊天应用程序。当 'Start Server'-Button 被按下时,我的 ServerController 创建了一个服务器对象,它在一个单独的线程上 运行ning。
这是我的问题:
每当我用默认的 'x'-Button 关闭 Window 时,服务器线程就会终止,但不会通知活动客户端服务器已终止。我需要通知客户服务器已关闭,就像我使用 'Stop-Server'-Button 所做的那样。我的服务器持有对控制器对象的引用。
public class ServerController {
@FXML
TextArea chatEvent_txt;
@FXML
Button start_btn;
@FXML
Button stop_btn;
private Server server;
private boolean started = false;
private StringBuffer chatEvents = new StringBuffer("");
/**
* @param e
*/
@FXML
public void startButtonAction(ActionEvent e) {
if (!started) {
this.server = new Server(this);
new Thread(server).start();
started = true;
chatEvents = chatEvents.append("Server started.." + "\n");
chatEvent_txt.setText(chatEvents.toString());
} else {
chatEvent_txt.setText("Server already started\n");
}
}
这是我的 'Stop-Server'- 通知所有客户端的按钮,服务器将关闭,然后关闭所有套接字和类似的东西。
@FXML
public void stopButtonAction(ActionEvent e) {
if (started) {
server.setRunning(false);
chatEvent_txt.setText("Server wurde gestoppt\n");
started = false;
}
}
方法setRunning();只会将一个变量设置为 false,这样线程就会离开接受新客户端的 while 循环。当 while 循环结束时,服务器将向所有客户端发送一条消息,以便他们知道服务器将关闭。
运行-我服务器上的方法:
@Override
public void run() {
try {
serverSocket.setSoTimeout(500);
while (running) {
try {
clientSocket = serverSocket.accept();
new Thread(new Listener(clientSocket, this)).start();
} catch (IOException e) {
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
try {
broadcastMessage(new Message(Message.Type.DISCONNECT_OK, "Server"));
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
如何让 'x'-Button 与 "Stop Server"-Button 执行相同的操作?
重构为
@FXML
public void stopButtonAction(ActionEvent e) {
shutdown();
}
public void shutdown() {
if (started) {
server.setRunning(false);
chatEvent_txt.setText("Server wurde gestoppt\n");
started = false;
}
}
然后当您加载并显示 FXML 时,您可以:
FXMLLoader loader = new FXMLLoader(getClass().getResource("/path/to/fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
someStage.setScene(scene);
ServerController controller = loader.getController();
someStage.setOnCloseRequest(e -> controller.shutdown());
如果您需要 window 在按下关闭按钮时不关闭(例如,如果您需要在以编程方式关闭 window 之前等待一切正常关闭),您可以调用 e.consume()
在 onCloseRequest
处理程序中。