java - 即使使用包装类,SwingWorker 异常也会丢失

标签 java swing swingworker

我一直在努力解决 SwingWorker 吃掉后台任务中抛出的任何异常的可用性问题,例如,描述 on this SO thread .该线程很好地描述了问题,但没有讨论恢复原始异常。

我收到的小程序需要向上传播异常。但我什至没能捕获它。我正在使用 this blog entry 中的 SimpleSwingWorker 包装器类专门尝试解决这个问题。这是一个相当小的类(class),但我会在最后重新发布它以供引用。

调用代码大致类似

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();
    }
}

最佳答案

忘掉你的包装器吧,它会吃掉异常,而 SwingWorker 不会。以下是应如何使用 SwingWorker,以及应如何处理从后台任务抛出的特定异常:

class MeaningOfLifeFinder extends SwingWorker<String, Object> {
    @Override
    public String doInBackground() throws SomeException {
        return findTheMeaningOfLife();
    }

    @Override
    protected void done() { // called in the EDT. You can update the GUI here, show error dialogs, etc.
        try { 
            String meaningOfLife = get(); // this line can throw InterruptedException or ExecutionException
            label.setText(meaningOfLife);
        } 
        catch (ExecutionException e) {
            Throwable cause = e.getCause(); // if SomeException was thrown by the background task, it's wrapped into the ExecutionException
            if (cause instanceof SomeException) {
                // TODO handle SomeException as you want to
            }
            else { // the wrapped throwable is a runtime exception or an error
                // TODO handle any other exception as you want to
            }
        }
        catch (InterruptedException ie) {
            // TODO handle the case where the background task was interrupted as you want to
        }
    }
}

关于java - 即使使用包装类,SwingWorker 异常也会丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13941236/

相关文章:

java - 从 WicketPanel 传递页面参数

java - hbase 仅获取行而不是空列(使用条件的现有列)- 使用 java 在 hbase 表中

java - 实际上如何使用 GraphStream 在 swing 中绘制图形?

java - Java 线程的未知行为

java - jFrame新线程

java - SwingWorker done() 调用了两次?

java - 号码识别程序

java - fragment 中使用的 webview 的后退按钮不起作用

java - 为什么我的 JLabel 没有在 Java GUI 中的 JPanel (GridBagLayout) 中间居中?

java - SwingWorker的done()方法似乎没有被调用? SwingWork 也没有取消或阻止,不使用发布/处理方法