我一直在努力解決SwingWorker在後臺任務中拋出任何異常的可用性問題,例如描述爲on this SO thread。該線程提供了一個很好的問題描述,但不討論恢復原始異常。即使使用包裝類時SwingWorker異常也會丟失
我上傳的小程序需要向上傳播異常。但我一直無法抓住它。我正在使用this blog entry中的SimpleSwingWorker包裝類來嘗試解決此問題。這是一個相當小的班,但我會在最後重新發布它,僅供參考。
調用代碼看起來像廣泛
try {
// lots of code here to prepare data, finishing with
SpecialDataHelper helper = new SpecialDataHelper(...stuff...);
helper.execute(); // this will call get+done on the actual worker
} catch (Throwable e) {
// used "Throwable" here in desperation to try and get
// anything at all to match, including unchecked exceptions
//
// no luck, this code is never ever used :-(
}
的包裝:
class SpecialDataHelper extends SimpleSwingWorker {
public SpecialDataHelper (SpecialData sd) {
this.stuff = etc etc etc;
}
public Void doInBackground() throws Exception {
OurCodeThatThrowsACheckedException(this.stuff);
return null;
}
protected void done() {
// called only when successful
// never reached if there's an error
}
}
的SimpleSwingWorker
的特點是實際的SwingWorker的done()/get()
方法被自動調用。理論上,這反映了背景中發生的任何異常。在實踐中,什麼都不會被捕獲,我甚至不知道爲什麼。
的SimpleSwingWorker類作參考,並一無所有的消隱爲簡潔:
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
/**
* A drop-in replacement for SwingWorker<Void,Void> but will not silently
* swallow exceptions during background execution.
*
* Taken from http://jonathangiles.net/blog/?p=341 with thanks.
*/
public abstract class SimpleSwingWorker {
private final SwingWorker<Void,Void> worker =
new SwingWorker<Void,Void>() {
@Override
protected Void doInBackground() throws Exception {
SimpleSwingWorker.this.doInBackground();
return null;
}
@Override
protected void done() {
// Exceptions are lost unless get() is called on the
// originating thread. We do so here.
try {
get();
} catch (final InterruptedException ex) {
throw new RuntimeException(ex);
} catch (final ExecutionException ex) {
throw new RuntimeException(ex.getCause());
}
SimpleSwingWorker.this.done();
}
};
public SimpleSwingWorker() {}
protected abstract Void doInBackground() throws Exception;
protected abstract void done();
public void execute() {
worker.execute();
}
}
這一切都是基於一個錯誤的假設。閱讀[javadoc的get()方法](http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#get%28%29):它會拋出一個ExecutionException if後臺計算引發異常。 –
另請參閱此[問與答](http://stackoverflow.com/q/7053865/230513)。 – trashgod
@JBNizet是的,這就是爲什麼SimpleSwingWorker的done()調用get()會捕獲ExecutionException並將其重新拋出爲新的RuntimeException。這不是重點嗎?如果沒有,那麼我們正在談論對方,你必須更加明確。 –