处理SwingWorker.doInBackground引发的异常的正确方法 [英] The proper way to handle exceptions thrown by the SwingWorker.doInBackground
问题描述
处理 SwingWorker
类用于调用 get
方法从< a href = http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#done() rel = nofollow noreferrer> 完成
方法,如此处和此处。
get
方法d表示以下内容:
The documentation for the get
method states the following:
等待完成计算所需的时间,然后检索
的结果。
Waits if necessary for the computation to complete, and then retrieves its result.
注意:在 Event Dispatch Thread 上调用 get
会阻止 all
事件,包括重绘,从处理到完成
SwingWorker
完成。
Note: calling get
on the Event Dispatch Thread blocks all
events, including repaints, from being processed until this
SwingWorker
is complete.
因此,如果 get
方法导致在 done
方法内等待,则实际上由于 done
方法是在EDT上执行的,因此会阻塞事件调度线程。
Therefore, if the get
method causes a waiting within the done
method, in fact it would block the Event Dispatch Thread, since the done
method is executed on EDT.
但是,在执行简单的操作之后测试建议的解决方案,您可能会注意到EDT没有被阻止:发生此现象的原因是在完成$中调用了
get
方法c $ c>方法,因此在计算操作结果之后将调用 get
,因此对其的调用不会阻止EDT。这种动机正确吗?
However, after performing a simple test of the proposed solution, you may notice that the EDT is not blocked: this behavior occurs because the get
method is invoked within the done
method, so get
is invoked after the result of the operation was calculated, and therefore the call to it will not block the EDT. Is this motivation correct?
推荐答案
因此,如果get方法导致在done方法中等待,实际上,它会阻塞事件调度线程,因为done方法是在EDT上执行的。
Therefore, if the get method causes a waiting within the done method, in fact it would block the Event Dispatch Thread, since the done method is executed on EDT.
实际上,如果调用了done, doInBackground
已经返回,因此在完成
内调用 get
不会阻止事件调度线程。
Actually, if done is called, the doInBackground
has already returned, therefore calling get
within done
will NOT block the Event Dispatching Thread.
如果您使用 PropertyChangeListener
支持并监视更改,情况也是如此。状态为 Done
The same goes if you are using the PropertyChangeListener
support and monitoring the change in state to DONE
已更新
因此,在查看 SwingWorker在 doInBackground之前调用完成之后'已完成,这意味着对被取消的工作人员调用 get
会无意地阻止EDT,基本的解决方法是y通过检查 SwingWorker#isCancelled
状态来忽略返回结果。让我们面对现实,如果取消了工作程序,则返回结果未知/不确定,因此最好不要尝试获取
它。
So, after having a look at SwingWorker calls 'done' before the 'doInBackground' is finished, which would mean that calling get
on a cancelled worker would block the EDT indeventially, the basic work around is actually to ignore the return result by checking the SwingWorker#isCancelled
state. Let's face it, if the worker is cancelled, the return result is unknown/undefined, so it's best NOT to try and get
it.
作为一个示例(基于错误中的代码)
As an example (based on the code from the 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);
}
}
这篇关于处理SwingWorker.doInBackground引发的异常的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!