Why is my GUI unresponsive while a SwingWorker thread runs?
I have a SwingWorker thread with an IOBound task which is totally locking up the interface while it runs. Swapping out the normal workload for a counter loop has the same result. The SwingWorker looks basically like this:
public class BackupWorker extends SwingWorker<String, String> {
private static String uname = null;
private static String pass = null;
private static String filename = null;
static String status = null;
BackupWorker (String uname, String pass, String filename) {
this.uname = uname;
this.pass = pass;
this.filename = filename;
}
@Override
protected String doInBackground() throws Exception {
BackupObject bak = newBackupObject(uname,pass,filename);
return "Done!";
}
}
The code that kicks it off lives in a class that extends JFrame:
public void actionPerformed(ActionEvent event) {
String cmd = event.getActionCommand();
if (BACKUP.equals(cmd)) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final StatusFrame statusFrame = new StatusFrame();
statusFrame.setVisible(true);
SwingUtilities.invokeLater(new Runnable() {
public void run () {
statusFrame.beginBackup(uname,pass,filename);
}
});
}
});
}
}
Here's the interesting part of StatusFrame:
public void beginBackup(final String uname, final String pass, final String filename) {
worker = new BackupWorker(uname, pass, filename);
worker.execute();
try {
开发者_JS百科 System.out.println(worker.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
So far as I can see, everything "long-running" is handled by the worker, and everything that touches the GUI on the EDT. Have I tangled things up somewhere, or am I expecting too much of SwingWorker?
I think the problem is due to the call to SwingWorker.get()
in your beginBackup
method. Take a look at the docs for this method:
Waits if necessary for the computation to complete, and then retrieves its result.
This is a blocking call, hence your GUI becomes unresponsive.
(Also, is there any particular reason why you're doing an invokeLater
from within an invokeLater
call? You're already running on the EDT.)
Read the section from the Swing tutorial on Tasks That Have Interim Results for a working example. You will see that the get(...) method is invoked from within the process(...) method that is overridden in the SwingWorker class.
精彩评论