SwingWorker exceptions lost even when using wrapper classes

后端 未结 3 1549
走了就别回头了
走了就别回头了 2021-02-02 02:11

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

3条回答
  •  星月不相逢
    2021-02-02 02:49

    The wrapper seems to works as expected. However, its implementation will never call done() if exception occurs. This is not suitable for many cases. It's probably simpler to call get() in done(). This will throw whatever exception that happened in doInBackground().

    Not sure how your example is structured, but it did not work in the application without EDT. So wrapping worker execution in SwingUtilities.invokeLater did help, ie:

    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new SpecialDataHelper().execute();
        }
    });
    

    The following example does print the exception stack trace:

    public class Tester {
    
        static class SpecialDataHelper extends SimpleSwingWorker {
            public SpecialDataHelper () {
            }
            public Void doInBackground() throws Exception {
                throw new Exception("test");
            }
            protected void done() {
            }
        }
    
        public static void main(String[] args) {
            try{
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        new SpecialDataHelper().execute();
                    }
                });
            } catch(Exception ex){
                ex.printStackTrace();
            }
        }
    }
    

    Also consider this simple example that demonstrates how to get the exceptions that occurred in doInBackground() without using the wrapper. The wrapper is just a helper in case you forget to call get().

    import javax.swing.JOptionPane;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    
    public class Tester {
        static class Worker extends SwingWorker {
            @Override
            protected Void doInBackground() throws Exception {
                throw new Exception("test");
            }
            @Override
            protected void done() {
                try {
                    get();
                    JOptionPane.showMessageDialog(null, "Operation completed");
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(null, "Operation failed");
                } 
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new Worker().execute();
                }
            });         
        }
    }
    

提交回复
热议问题