Error handling in SwingWorker

别来无恙 提交于 2020-01-11 08:54:29

问题


My question is a theory-based question, but it does meet a specific need I have.

What do you do when your SwingWorker throws an Exception that you a) can anticipate and b) need to recover from and continue, but you want to notify the user that this error has happened? How do you grab the expected exception and notify the user without violating the "No Swing code from doInBackground()" rule?

I have, in consideration of this problem, developed a SSCCE that I would like to put forth with the questions below it.

SSCCE:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Test {

    public static void main(String args[]) {
        final JFrame frame = new JFrame();
        JButton go = new JButton("Go.");
        go.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Task(frame);
            }
        });
        frame.add(go);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    static class Task extends SwingWorker<Void, Void> {
        JFrame parent;
        JDialog dialog;
        public Task(JFrame parent) {
            this.parent = parent;
            dialog = new JDialog(parent);
            JProgressBar jpb = new JProgressBar();
            jpb.setIndeterminate(true);
            dialog.add(jpb);
            dialog.setLocationRelativeTo(null);
            dialog.setVisible(true);
            execute();
        }

        @Override
        protected Void doInBackground() throws Exception {
            for(int i = 0; i < 100000; i++) {
                System.out.println(i);
                try {
                    if(i == 68456) throw new IllegalStateException("Yikes! i = 68456.");
                } catch (final IllegalStateException e) {
                    SwingUtilities.invokeAndWait(new Runnable() {
                        @Override
                        public void run() {
                            JOptionPane.showMessageDialog(parent, "Error: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                        }
                    });
                }
            }
            return null;
        }

        @Override
        protected void done() {
            if (!isCancelled()) {
                try {
                    get();
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("done");
            dialog.dispose();
        }

    }
}

Is it valid to call SwingUtilities.invokeAndWait() within the doInBackground() method? I did some Thread profiling on this and the results were thus:

Once the "Go" button is pressed, the SwingWorker-pool-1-thread-1 thread goes Green. THEN, when the if condition is met, the error is thrown, and the error dialog is displayed, the thread goes yellow, and there is indeed a green "blip" on the AWT-EventQueue-0 thread, indicating that the EDT was invoked. I waited about 10 seconds, pressed "ok," and the SwingWorker thread went green again.

Are there any potential pitfalls to doing something like this? Does anyone have experience with notifying users of computation errors in real time from the SwingWorker?

I'll be honest, this approach has me leery. It seems unorthodox but I cannot say for certain whether this is a bad idea.


回答1:


I see no problem with using invokeAndWait() when the user actually needs to approve. If not, as shown in this example, a SwingWorker<Void, String> can simply call publish() with data and error messages interleaved. A suitable message appended in done() would allow the user to review the accumulated output if necessary.



来源:https://stackoverflow.com/questions/20569780/error-handling-in-swingworker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!