处理SwingWorker.doInBackground引发的异常的正确方法

时间:2015-09-07 20:51:44

标签: java swing exception swingworker event-dispatch-thread

处理doInBackground类的SwingWorker方法引发的异常的正确方法是从get方法中调用done方法,如所解释的那样{{3 }和here

here方法的文档说明如下:

  

如果需要等待计算完成,然后检索   结果。

     

注意:在事件调度线程上调用get阻止所有   事件,包括重绘,直到处理   SwingWorker已完成。

因此,如果get方法导致done方法内的等待,实际上它会阻止事件调度线程,因为done方法在EDT上执行。

但是,在对提议的解决方案执行简单测试后,您可能会注意到EDT未被阻止:出现这种情况是因为在get方法中调用了done方法,因此{{在计算操作结果后调用1}},因此对它的调用不会阻止EDT。这种动机是否正确?

2 个答案:

答案 0 :(得分:3)

  

因此,如果get方法在done方法中导致等待,实际上它会阻塞事件调度线程,因为在EDT上执行了done方法。

实际上,如果调用done,则doInBackground已经返回,因此在get内调用done将不会阻止事件调度线程。

如果您使用PropertyChangeListener支持并监控状态更改为DONE

,则同样如此

<强>更新

因此,在查看SwingWorker calls 'done' before the 'doInBackground' is finished之后,这意味着对取消的工作者调用get将会破坏EDT,基本的工作实际上是通过检查返回结果来忽略返回结果SwingWorker#isCancelled州。让我们面对现实,如果工人被取消,返回结果是未知/未定义的,所以最好不要尝试get

作为一个例子(基于bug的代码)

import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        SwingWorker<String, String> worker = new SwingWorker<String, String>() {
            @Override
            protected String doInBackground() throws Exception {
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        System.out.println("Working...");
                        Thread.sleep(1000);

                    }
                } catch (InterruptedException ex) {
                    System.out.println("Got interrupted!");
                }

                try {
                    System.out.println("Cleaning up");
                    Thread.sleep(10000);
                    System.out.println("Done cleaning");
                } catch (InterruptedException ex) {
                    System.out.println("Got interrupted second time!");
                }

                return null;
            }

            @Override
            protected void done() {
                System.out.println("Done");
                if (!isCancelled()) {
                    long start = System.currentTimeMillis();
                    try {
                        get();
                    } catch (InterruptedException | ExecutionException ex) {
                        ex.printStackTrace();
                    }
                    long end = System.currentTimeMillis();
                    System.out.println("Took " + ((end - start) / 1000d));
                } else {
                    System.out.println("Was cancelled");
                }
            }
        };

        worker.execute();

        Thread.sleep(10000);

        worker.cancel(true);
        Thread.sleep(20000);
    }
}

答案 1 :(得分:0)

@Override
protected void done()
{
    try
    {
        if(!super.isCancelled())
        {
            super.get();
        }
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
}