即使使用包装类,SwingWorker异常也会丢失 [英] SwingWorker exceptions lost even when using wrapper classes

查看:109
本文介绍了即使使用包装类,SwingWorker异常也会丢失的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力解决SwingWorker的可用性问题,该问题包含后台任务中抛出的任何异常,例如,描述。该线程给出了一个很好的问题描述,但没有讨论恢复原始异常。

I've been struggling with the usability problem of SwingWorker eating any exceptions thrown in the background task, for example, described on this SO thread. That thread gives a nice description of the problem, but doesn't discuss recovering the original exception.

我已经提交的applet需要向上传播异常。但我甚至无法抓住它。我正在使用此博客条目中的SimpleSwingWorker包装类来专门尝试解决此问题。这是一个相当小的课程,但我会在最后重新发布它仅供参考。

The applet I've been handed needs to propagate the exception upwards. But I haven't been able to even catch it. I'm using the SimpleSwingWorker wrapper class from this blog entry specifically to try and address this issue. It's a fairly small class but I'll repost it at the end here just for reference.

调用代码看起来大致类似于

The calling code looks broadly like

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()方法会自动调用。理论,重新抛出在后台发生的任何异常。在实践中,没有任何东西被捕获,我甚至不知道为什么。

The feature of SimpleSwingWorker is that the actual SwingWorker's done()/get() methods are automatically called. This, in theory, rethrows any exceptions that happened in the background. In practice, nothing is ever caught, and I don't even know why.

SimpleSwingWorker类,供参考,为简洁而没有任何遗漏:

The SimpleSwingWorker class, for reference, and with nothing elided for brevity:

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,以及如何处理从后台任务抛出的特定异常:

Forget about your wrapper, which eats the exceptions, whereas the SwingWorker doesn't. Here's how a SwingWorker should be used, and how you should handle a specific exception thrown from the background task:

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
        }
    }
}

这篇关于即使使用包装类,SwingWorker异常也会丢失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆