Swing Frage zu SwingWorker Verhalten bei cancel()

Diskutiere Frage zu SwingWorker Verhalten bei cancel() im AWT, Swing, JavaFX & SWT Forum; Hallo, ich habe ein Problem, bzw. ein Verhalten, was ich mir nicht ganz erklären kann und worfür ich eine Lösung suche. Ich habe ein GUI aus dem...

  1. ralfb1105
    ralfb1105 Mitglied
    Hallo,

    ich habe ein Problem, bzw. ein Verhalten, was ich mir nicht ganz erklären kann und worfür ich eine Lösung suche. Ich habe ein GUI aus dem ich einen Test starte, der dann eine gewisse Zeit läuft und dann beendet wird oder vorher über einen Stop Button beendet wird. Das Ganze habe ich mit SwingWorker Threads realisiert. Hier als Referenz der komplette Code:
    Code (Java):
    package oracle;

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.text.DecimalFormat;
    import java.util.List;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.UUID;
    import java.util.Vector;
    import java.util.concurrent.TimeUnit;
    import javax.swing.Icon;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JScrollPane;
    import javax.swing.JSlider;
    import javax.swing.JTextArea;
    import javax.swing.JToggleButton;
    import javax.swing.WindowConstants;
    import javax.swing.border.BevelBorder;
    import javax.swing.border.SoftBevelBorder;
    import javax.swing.SwingUtilities;
    import javax.swing.SwingWorker;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.ThreadPoolExecutor;


    /**
    * This code was edited or generated using CloudGarden's Jigloo
    * SWT/Swing GUI Builder, which is free for non-commercial
    * use. If Jigloo is being used commercially (ie, by a corporation,
    * company or business for any purpose whatever) then you
    * should purchase a license for each developer using Jigloo.
    * Please visit www.cloudgarden.com for details.
    * Use of Jigloo implies acceptance of these licensing terms.
    * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
    * THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
    * LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
    */

    @SuppressWarnings("serial")
    public class TestMultipleUser extends javax.swing.JFrame {
        private JTextArea jTAOutput;
        private JButton jBExit;
        private JToggleButton jTBStartStop;
        private JSlider jSNoUser;
        private JLabel jLabel1;
        private JLabel jLTestRemaining;
        private JScrollPane jScrollPane1;
        private ProcessWorkerCounter pc;
        private Vector<ProcessWorkerDbTest> vcDbTest;
       
       
        /**
        * Auto-generated main method to display this JFrame
        */

       
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    TestMultipleUser inst = new TestMultipleUser();
                    inst.setLocationRelativeTo(null);
                    inst.setVisible(true);
                }
            });  
        }
       
        public class ProcessWorkerCounter extends SwingWorker<Void, String>
        {
            private JLabel jLCounter;
            private long seconds;
            private Timer timerCounter;
            private Vector<ProcessWorkerDbTest> vcDbTest;
            private ExecutorService esDbTest;
           
            //Konstruktor
            public ProcessWorkerCounter(JLabel counter, long seconds, Vector<ProcessWorkerDbTest> vcDbTest)
            {
                this.jLCounter = counter;
                this.seconds = seconds;
                this.vcDbTest = vcDbTest;
            }
           
            //getter - Return Timer Object
            public Timer getTimerCounter() {
                return timerCounter;
            }
           
            class TaskCounter extends TimerTask
            {
               
              @Override public void run()
              {
                  seconds--;
                  long hh = seconds / 3600;
                  long mm = (seconds % 3600) / 60;
                  long ss = seconds - (hh * 3600) - (mm * 60);
                  DecimalFormat format = new DecimalFormat("00");
                  publish(format.format(hh) + ":" + format.format(mm) + ":" + format.format(ss));
                  if (seconds == 0) {
                      for (int i=0; i < vcDbTest.size(); i++) {
                          ((ProcessWorkerDbTest)vcDbTest.elementAt(i)).cancel(true);
                        }
                      pc.getTimerCounter().cancel();
                    publish("Test finished!");
                  }
              }
            }
       
            @Override
            protected Void doInBackground() throws Exception
            {
                //hier l�uft alles in einem eigenen Thread (nebenl�ufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert.
               
                this.timerCounter = new Timer();
                timerCounter.scheduleAtFixedRate(new TaskCounter(), 0, 1000);
               
                //System.out.println("Start Tests: " + vcDbTest.size());
                this.esDbTest = new ThreadPoolExecutor(33, 33, 1L,TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
               
                for (int i=0; i < vcDbTest.size(); i++) {
                    esDbTest.execute((Runnable)vcDbTest.elementAt(i));
                }  
                return null;
            }
           
            @Override
            protected void process(List<String> chunks)
            {
                //hier l�uft alles auf dem EDT (Event Dispatch Thread). Darum k�nnen (und sollten) wir hier die GUI Komponenten manipulieren.
                for(int i = 0; i < chunks.size(); i++)
                {
                    jLCounter.setText(chunks.get(i));
                    //jTAOutput.append(System.getProperty("line.separator"));
                }
            }
        }
       
        public class ProcessWorkerDbTest extends SwingWorker<Void, String>
        {
            private JTextArea jTAOutput;
           
            public ProcessWorkerDbTest(JTextArea textArea)
            {
                this.jTAOutput = textArea;
            }

            @Override
            protected Void doInBackground() throws Exception
            {
                //hier l�uft alles in einem eigenen Thread (nebenl�ufig) ab. Es ist also egal wie lange die Abarbeitung hier dauert.
                UUID uuid = UUID.randomUUID();
                final String randomUUIDString = uuid.toString();
                while (!isCancelled()) {
                    for (int i=1000; i>=0; i--) {
                        //System.out.println("DB Test " + randomUUIDString + " Run: " + i);
                        publish("DB Test " + randomUUIDString + " Run: " + i);
                        TimeUnit.SECONDS.sleep(1);
                    }
                }
                System.out.println("DB Test " + randomUUIDString + " Finished!");
                return null;
            }
           
            @Override
            protected void process(List<String> chunks)
            {
                //hier l�uft alles auf dem EDT (Event Dispatch Thread). Darum k�nnen (und sollten) wir hier die GUI Komponenten manipulieren.
                for(int i = 0; i < chunks.size(); i++)
                {
                    jTAOutput.append(chunks.get(i));
                    jTAOutput.append(System.getProperty("line.separator"));
                }
            }
        }
       
       
        public class TestTableSize {
            private String name;
            private int size;
           
            public TestTableSize(String name, int size) {
                this.name = name;
                this.size = size;
            }
           
            public String getTestTableSize() {
                return this.name + ":" + this.size + " MB";
            }
           
            public String getName() {
                return this.name;
            }
           
            public int getSize() {
                return this.size;
            }
        }
       
       
        public TestMultipleUser() {
            super();
            initGUI();
        }
       
        private void initGUI() {
            try {
                setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
                getContentPane().setLayout(null);
                this.setTitle("Test Multiple User");
                {
                    jScrollPane1 = new JScrollPane();
                    getContentPane().add(jScrollPane1);
                    jScrollPane1.setBounds(24, 142, 816, 216);
                    {
                        jTAOutput = new JTextArea();
                        jScrollPane1.setViewportView(jTAOutput);
                        jTAOutput.setBounds(24, 142, 816, 216);
                        jTAOutput.setEditable(false);
                    }
                }
                {
                    jBExit = new JButton();
                    getContentPane().add(jBExit);
                    jBExit.setText("Exit");
                    jBExit.setBounds(852, 335, 80, 23);
                    jBExit.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent evt) {
                            jBExitActionPerformed(evt);
                        }
                    });
                }
                {
                    jLTestRemaining = new JLabel();
                    getContentPane().add(jLTestRemaining);
                    jLTestRemaining.setBounds(136, 110, 130, 20);
                    jLTestRemaining.setBorder(new SoftBevelBorder(BevelBorder.LOWERED, null, null, null, null));
                }
                {
                    jLabel1 = new JLabel();
                    getContentPane().add(jLabel1);
                    jLabel1.setText("Remining Time");
                    jLabel1.setBounds(36, 114, 111, 16);
                }
                {

                    jSNoUser = new JSlider();
                    getContentPane().add(jSNoUser);
                    getContentPane().add(getJTBStartStop());

                    jSNoUser.setBounds(352, 81, 237, 45);
                    jSNoUser.setMinimum(1);
                    jSNoUser.setMaximum(33);
                    jSNoUser.setMajorTickSpacing(4);
                    jSNoUser.setMinorTickSpacing(1);
                    jSNoUser.createStandardLabels(1);
                    jSNoUser.setPaintLabels(true);
                    jSNoUser.setPaintTicks(true);
                    jSNoUser.setValue(4);
                    jSNoUser.setFont(new java.awt.Font("Segoe UI",0,11));
                }
                pack();
                this.setSize(959, 431);
            } catch (Exception e) {
                //add your error handling code here
                e.printStackTrace();
            }
        }
       
        private void jBExitActionPerformed(ActionEvent evt) {
            System.exit(0);
        }
       
        private void jTBStartStopActionPerformed(ActionEvent evt) {
            toggleButtonAction();
        }
       
        private void toggleButtonAction() {
            if (jTBStartStop.isSelected()) {
                long seconds = 30;
               
                this.vcDbTest = new Vector<ProcessWorkerDbTest>();
               
                for (int i = 1; i <= jSNoUser.getValue(); i++) {
                    vcDbTest.add(new ProcessWorkerDbTest(jTAOutput));
                }
               
                this.pc = new ProcessWorkerCounter(jLTestRemaining, seconds, vcDbTest);
                pc.execute();
            } else {
                System.out.println("Stop Tests: " + vcDbTest.size());
                for (int i=0; i < vcDbTest.size(); i++) {
                      ((ProcessWorkerDbTest)vcDbTest.elementAt(i)).cancel(true);
                    }
                pc.getTimerCounter().cancel();
                System.out.println("Test stopped!!");
            }
        }
       
        private JToggleButton getJTBStartStop() {
            if(jTBStartStop == null) {
                Icon icon = new ImageIcon("StartTriangel20.png");
                jTBStartStop = new JToggleButton("", icon);
                getContentPane().add(jTBStartStop);
                jTBStartStop.setBounds(641, 72, 20, 20);
                jTBStartStop.setBorderPainted(false);
                jTBStartStop.setIcon(new ImageIcon(getClass().getClassLoader().getResource("StartTriangel20.png")));
                jTBStartStop.setSelectedIcon(new ImageIcon(getClass().getClassLoader().getResource("StopQuad20.png")));
                jTBStartStop.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt) {
                        jTBStartStopActionPerformed(evt);
                    }
                });
                jTBStartStop.setVisible(true);
            }
            return jTBStartStop;
        }
    }
     
    Das Problem:
    Wenn ich den Stop Button drücke bzw. die Zeit abgelaufen ist wird der Thread über die cancel() Methode
    Code (Java):
    for (int i=0; i < vcDbTest.size(); i++) {
                      ((ProcessWorkerDbTest)vcDbTest.elementAt(i)).cancel(true);
                    }
    beendet:
    Code (Java):
    private void toggleButtonAction() {
            if (jTBStartStop.isSelected()) {
                long seconds = 30;
               
                this.vcDbTest = new Vector<ProcessWorkerDbTest>();
               
                for (int i = 1; i <= jSNoUser.getValue(); i++) {
                    vcDbTest.add(new ProcessWorkerDbTest(jTAOutput));
                }
               
                this.pc = new ProcessWorkerCounter(jLTestRemaining, seconds, vcDbTest);
                pc.execute();
            } else {
                System.out.println("Stop Tests: " + vcDbTest.size());
                for (int i=0; i < vcDbTest.size(); i++) {
                      ((ProcessWorkerDbTest)vcDbTest.elementAt(i)).cancel(true);
                    }
                pc.getTimerCounter().cancel();
                System.out.println("Test stopped!!");
            }
        }
    Beim cancel() wird der Thread beendet, aber es wird anscheinend der Code der nach der while-Schleife steht nicht mehr ausgeführt:
    Code (Java):
    while (!isCancelled()) {
                    for (int i=1000; i>=0; i--) {
                        //System.out.println("DB Test " + randomUUIDString + " Run: " + i);
                        publish("DB Test " + randomUUIDString + " Run: " + i);
                        TimeUnit.SECONDS.sleep(1);
                    }
                }
                System.out.println("DB Test " + randomUUIDString + " Finished!");
                return null;
    Ich sehe auf der Console den Text "Test Stopped" aber nicht den Text "System.out.println("DB Test " + randomUUIDString + " Finished!");" aus den einzelnen ProcessWorkerDbTest Threads!?

    Für mich wäre es wichtig nach beenden der DB Tests Code auszuführen um "aufzuräumen", sprich z.B. die DB Sessions zu terminieren, etc.

    Hat jemand eine Erklärung/Idee was ich hier falsch mache und warum dieser Code nicht mehr ausgeführt wird?

    Gruß

    Ralf
     
  2. Robat
    Robat Bekanntes Mitglied
    Der Code der nach doInBackground() ausgeführt werden soll, sollte in der done() Methode stehen.
    Code (Java):

    @Override
    protected void done() {
        // stuff after task finished
    }
     
  3. ralfb1105
    ralfb1105 Mitglied
    Hallo Robat,

    DANKE :) genau das hat mir gefehlt. Jetzt läuft es.

    Gruß

    Ralf
     
Die Seite wird geladen...

Frage zu SwingWorker Verhalten bei cancel() - Ähnliche Themen

Frage zu Swing,Threads, SwingWorker und Socket Communikation
Frage zu Swing,Threads, SwingWorker und Socket Communikation im Forum AWT, Swing, JavaFX & SWT
Frage zu ProgressBar, SwingWorker etc.
Frage zu ProgressBar, SwingWorker etc. im Forum AWT, Swing, JavaFX & SWT
SwingWorker Statusabfrage
SwingWorker Statusabfrage im Forum AWT, Swing, JavaFX & SWT
Frage um den Code bildlich darzustellen
Frage um den Code bildlich darzustellen im Forum Java Basics - Anfänger-Themen
DoodleJump programmieren: Kollisionsabfrage
DoodleJump programmieren: Kollisionsabfrage im Forum Spiele- und Multimedia-Programmierung
Thema: Frage zu SwingWorker Verhalten bei cancel()