我正在制作一个基于 Java 的服务器应用程序。由于某种原因,当我从服务器检索文件列表时,我的 GUI 被锁定。我向服务器发送一条消息“listFiles”,然后服务器以“LIST”响应 - 这是执行下面的代码的时间。
private Boolean wait = true;
// Handle server output.
private class ServerOutput implements Runnable {
public void run() {
String serverMsg;
while ((serverMsg = reader.nextLine()) != null) {
try {
if (serverMsg.equals("LIST")) {
wait = true;
fileList = new ObjectInputStream(socket.getInputStream()).readObject();
fileArray = (File[]) fileList;
for(File file : fileArray){
System.out.println(file.getName());
}
wait = false;
}
public Boolean getState(){
return wait;
}
public File[] getFileList(){
return fileArray;
}
...
GUI 应陷入 while 循环,直到“wait = true”。有时它可以工作,有时它只是卡在循环中,即使客户端肯定已经收到了 fileList,因为它成功地将其打印出来。
以下是附加到连接按钮的操作监听器的代码:
try {
fc = new FileClient(serverAddress, serverPort);
fc.send("listFiles","null");
while (fc.getState()) {
}
File[] fileList = fc.getFileList();
...
最佳答案
您的代码在 Swing 事件线程上调用 while (...)
循环,公然违反了 Swing 线程规则。不要那样做。而是使用 SwingWorker。通过向 SwingWorker 添加 PropertyChangeWorker,您可以轻松收到通知,一旦完成,就可以通过在工作线程上调用 get()
来提取它返回的结果。 SwingWorker Tutorial可以向您展示详细信息。
您的代码可能类似于:
@Override
public void actionPerformed(ActionEvent e) {
// create the SwingWorker
MyFileWorker myFileWorker = new MyFileWorker();
// attach a PropertyChangeListener to it
myFileWorker.addPropertyChangeListener(new MyFileWorkerListener());
// and run the worker
myFileWorker.execute();
}
和其他地方:
private class MyFileWorker extends SwingWorker<File[], Void> {
// must initialize the readers, sockets....
// probably with data passed into this worker's construtor
private BufferedReader reader = null; // fix this
private Socket socket = null; // fix this
@Override
protected File[] doInBackground() throws Exception {
String serverMsg;
while ((serverMsg = reader.readLine()) != null) {
if (serverMsg.equals("LIST")) {
File[] fileArray = (File[]) new ObjectInputStream(socket.getInputStream()).readObject();
return fileArray;
}
}
// if LIST never found
return null;
}
}
private class MyFileWorkerListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() != SwingWorker.StateValue.DONE) {
return;
}
MyFileWorker myFileWorker = (MyFileWorker) evt.getSource();
try {
// get File array
files = myFileWorker.get();
// here notify GUI that files have been found
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
关于Java GUI 锁定 - boolean 值未按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34048391/