fbielejec fbielejec - 6 months ago 20
Java Question

Graceful exception handling in Swing Worker

I am using threading in application through Swing Worker class. It works fine, yet I have a bad feeling about showing an error message dialog in try-catch block. Can it potentially block the application? This is what it looks right now:

SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {

// Executed in background thread
public Void doInBackground() {
try {
DoFancyStuff();
} catch (Exception e) {

e.printStackTrace();

String msg = String.format("Unexpected problem: %s", e
.toString());

//TODO: executed in background thread and should be executed in EDT?
JOptionPane.showMessageDialog(Utils.getActiveFrame(),
msg, "Error", JOptionPane.ERROR_MESSAGE,
errorIcon);

}//END: try-catch

return null;
}

// Executed in event dispatch thread
public void done() {
System.out.println("Done");
}
};


Can it be done in a safe way using Swing Worker framework? Is overriding publish() method a good lead here?

EDIT:

Did it like this:

} catch (final Exception e) {

SwingUtilities.invokeLater(new Runnable() {

public void run() {

e.printStackTrace();

String msg = String.format(
"Unexpected problem: %s", e.toString());

JOptionPane.showMessageDialog(Utils
.getActiveFrame(), msg, "Error",
JOptionPane.ERROR_MESSAGE, errorIcon);

}
});

}


Calling get in done method would result in two try-catch blocks, as the computational part throws exceptions, so I think this is cleaner in the end.

mre mre
Answer

One option is to use SwingUtilities.invokeLater(...) to post the action on the EDT

SwingUtilities.invokeLater(new Runnable(){
    @Override
    public void run(){
        JOptionPane.showMessageDialog(
            Utils.getActiveFrame(),
            msg, 
            "Error", 
            JOptionPane.ERROR_MESSAGE,
            errorIcon);
    }
});

And as you noted, SwingWorker is capable of reporting intermediate results, but you'll need to override process(...), which is called when you invoke publish(...).

Regardless, why not just set a flag if an exception occurs, and if that flag is set, show the dialog in done() since it's executed safely in the EDT?