SwingWorker的done方法甚至在doInBackground完成之前随机执行

时间:2013-09-13 04:56:33

标签: 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 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

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

1 个答案:

答案 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的这种行为外,没有其他解释。