3

我有一段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,SwingWorkerdone方法是在doInBackground完成之前执行的。(你需要多次执行上面的JFrame才能产生问题)

-> 0
-> 1
-> 2
-> 3
-> 4
DONE!!!
interrupted in doInBackground

我可以知道为什么会这样吗?

4

1 回答 1

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执行“打开文件”例程,定期创建 Swing 组件并将它们添加到 GUI。
  • 取消时(通过带有Cancel按钮的进度条对话框),done将删除在doInBackground.

有时这些操作会重叠,并且会在执行擦除doInBackground后继续创建组件。done对用户来说,它看起来就像按下Cancel只是偶尔不起作用,除了调试显示done正在被调用。除了这种行为之外,没有其他解释SwingWorker

于 2013-10-17T21:09:25.007 回答