处理doInBackground
类的SwingWorker
方法引发的异常的正确方法是从get
方法中调用done
方法,如所解释的那样{{3 }和here。
here方法的文档说明如下:
如果需要等待计算完成,然后检索 结果。
注意:在事件调度线程上调用
get
阻止所有 事件,包括重绘,直到处理SwingWorker
已完成。
因此,如果get
方法导致done
方法内的等待,实际上它会阻止事件调度线程,因为done
方法在EDT上执行。
但是,在对提议的解决方案执行简单测试后,您可能会注意到EDT未被阻止:出现这种情况是因为在get
方法中调用了done
方法,因此{{在计算操作结果后调用1}},因此对它的调用不会阻止EDT。这种动机是否正确?
答案 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();
}
}