Java SwingWorker';s done方法甚至在doInBackground完成之前随机执行
我有一段Java SwingWorker';s done方法甚至在doInBackground完成之前随机执行,java,multithreading,swing,swingworker,Java,Multithreading,Swing,Swingworker,我有一段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 Ja
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);
}
}
我可以知道为什么吗?从Howard的评论来看,这可能是一个bug
我也遇到过这个问题。我倾向于将清理放在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) {
// ...
}
}
(如果需要从doInBackground
更新GUI,请记住使用invokeLater
)
在我的情况下,我有这样的事情:
执行“打开文件”例程,定期创建Swing组件并将其添加到GUI中doInBackground
- 取消时(通过带有取消按钮的进度条对话框),
将删除done
期间创建的所有组件doInBackground
有时,这些操作会重叠,
doInBackground
会在执行擦除后继续创建组件。对用户来说,按Cancel键似乎偶尔不起作用,只是调试显示正在调用done
。没有其他解释,除了SwingWorker的这种行为这可能是一个与stdoutIf的竞争条件的演示,如果程序员是对的,包括sysout调用上的时间戳应该显示它。。。跟踪这一点的一个策略是在IDE中为Swingworker插入源代码,并在done和doInBackgroun的最后一步上设置断点。。。只是一个想法…这不是仅仅因为在EDT上调用了done,并且doInBackground在它自己的线程上运行,所以它们不必一个接一个地出现吗?并自动取消已完成的呼叫。另外,只要在打印之前在catch块中添加另一个sleep,您每次都会看到它。支持SwingWorker
的Future
正在取消,并且在同一线程的上下文中调用了done
方法。这意味着doInBackground
方法正在运行的Thread
被调度运行并检测中断之前,可能会执行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) {
// ...
}
}