我有一段JFrame
代码,在代码关闭时停止SwingWorker
:
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
/**
*
* @author yccheok
*/
public class JavaApplication11 extends JFrame {
public JavaApplication11() {
this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
final Task task = new Task();
task.execute();
addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
if (task != null) {
task.cancel(true);
}
}
});
}
public class Task extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() {
for (int i = 0; i < 1000; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.out.println("interrupted in doInBackground");
break;
}
System.out.println("-> " + i);
}
return null;
}
@Override
public void done() {
System.out.println("DONE!!!");
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new JavaApplication11().setVisible(true);
}
}
然而,随机地,我意识到当我关闭JFrame
时,SwingWorker
的{{1}}方法会在done
完成之前执行。 (您需要多次执行上面的JFrame才能产生问题)
doInBackground
我可以知道为什么会这样吗?
答案 0 :(得分:2)
根据霍华德的评论,http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6826514表明这可能是一个错误。
我也参与其中。如果它依赖于顺序,我倾向于将清理放在doInBackground
内,并且仅使用done
进行异常处理。
@Override
protected Void doInBackground() {
try {
// ...
} finally {
// some cleanup inside 'doInBackground'
if (isCancelled()) {
// ...
} else {
// ...
}
}
return (Void) null;
}
@Override
protected void done() {
try {
get();
} catch (CancellationException x) {
// ...
} catch (InterruptedException x) {
// ...
} catch (ExecutionException x) {
// ...
}
}
(如果您需要从invokeLater
更新GUI,请记得使用doInBackground
。)
在我的情况下,我有这样的事情:
doInBackground
执行&#34;打开文件&#34;例程,定期创建Swing组件并将其添加到GUI。done
将删除doInBackground
期间创建的所有组件。有时这些操作会重叠,doInBackground
会在done
执行擦除后继续创建组件。对于用户来说,看起来像按取消只是偶尔不工作,除了调试显示正在调用done
。除了SwingWorker
的这种行为外,没有其他解释。