Tôi đã đấu tranh với vấn đề về khả năng sử dụng của SwingWorker khi ăn bất kỳ ngoại lệ nào được ném trong tác vụ nền, ví dụ, được mô tả on this SO thread. Chủ đề đó đưa ra một mô tả tốt đẹp về vấn đề, nhưng không thảo luận về việc khôi phục ngoại lệ ban đầu.Trường hợp ngoại lệ SwingWorker bị mất ngay cả khi sử dụng các lớp bao bọc
Ứng dụng tôi đã được trao nhu cầu truyền bá ngoại lệ trở lên. Nhưng tôi đã không thể bắt được nó. Tôi đang sử dụng lớp wrapper SimpleSwingWorker từ this blog entry đặc biệt để thử và giải quyết vấn đề này. Đó là một lớp học khá nhỏ nhưng tôi sẽ repost nó ở cuối đây chỉ để tham khảo.
Mã gọi trông rộng rãi như
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 :-(
}
Các wrappers:
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
}
}
Các tính năng của SimpleSwingWorker
là done()/get()
phương pháp SwingWorker thực tế của sẽ được tự động gọi. Điều này, về mặt lý thuyết, sẽ trả lại bất kỳ ngoại lệ nào đã xảy ra trong nền. Trong thực tế, không có gì là bao giờ bị bắt, và tôi thậm chí không biết tại sao.
Lớp SimpleSwingWorker, để tham khảo, và không có gì elided cho ngắn gọn:
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();
}
}
Tất cả điều này được dựa trên giả định sai. Đọc [javadoc cho phương thức get()] (http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#get%28%29): nó ném một ExecutionException nếu tính toán nền đã ném một ngoại lệ. –
Xem thêm [Hỏi đáp] này (http://stackoverflow.com/q/7053865/230513). – trashgod
@JBNizet Có, đó là lý do tại sao các cuộc gọi() của SimpleSwingWorker nhận được(), bắt ExecutionException và trả về nó như là một RuntimeException mới. Đó không phải là vấn đề? Nếu không, thì chúng ta đang nói chuyện với nhau và bạn sẽ phải rõ ràng hơn. –