Threads SwingWorker läuft trotz cancel weiter

Casio12

Mitglied
Hallo, ich habe folgende Klasse von SwingWorker erstellt, er wird benutzt um eine Tabelle zu aktualisieren.
Java:
public class MyWorker extends SwingWorker< Void, Void >
{
    protected Void doInBackground() throws Exception
    {
        while( ! this.isCancelled() )
        {
           // Blockierende Warteschlange,
            // Tu was, wenn Daten in Warteschlange verfügbar
            Thread.sleep( 5 );
        }
        return null;
    }

    protected void done()
    {
        try
        {
            System.out.println( "Done: " + this.getState() );
        
        }
        catch ( CancellationException e)
        {
            System.out.println( "Cancel: " + this.getState() );
        }
    }
}
Über einen Button erzeuge und starte ich den Thread:
Java:
        if( this.buttonStart == e.getSource() )
        {
            this.mySw = new MyWorker(  );
            this.mySw.execute();
         }
Über einen weiteren Button beende ich den Thread:
Java:
          else if( this.buttonStop == e.getSource() )
         {
             this.mySw.cancel( true );
         }
Der Thread wird gestartet und die doInBackground() läuft und bei Stop wird done()ausgeführt. Im Eclipse Debug-Fenster bleibt der Thread jedoch als running bestehen.
Bei erneutem betätigen vom Start-Button wird ein neuer Thread im Debug-Fenster erstellt, so lange bis dort 10 Threads sind.
Diese haben alle den Status running. Beim setzen von Breakpoints lande ich in verschiedenen Threads.

Wieso wird der Thread nicht beendet?
 
Zuletzt bearbeitet von einem Moderator:
Das klingt schon mal gut.
Dadurch, dass ein erzeugter Thread nicht beendet wird, bevor ich einen neuen erzeuge kommt es zu Fehlverhalten meiner Anwendung.

Ich hatte angenommen, dass ein beendeter Thread auch aus der Debug-Ansicht verschwindet.
Stattdessen werden die Threads mehr und ab dem zehnten wird ein beliebiger Thread von denen wieder ausgeführt.

Hatte mal gelesen das sich SwingWorker aus einem Threadpool bedient. Und dann beendete wieder neu erzeugt.

Kann ich prüfen ob ein Thread wirklich beendet ist? in done() erhalte ich den Status des Threads DONE.

Oder liegt es an noch bestehenden Referenzen in dem Thread auf andere Objekte, dass dieser nicht beendet wird? Wie z.B. auf eine Warteschlange, die vom einem anderen Thread gefüllt wird?
 
So genau kenne ich mich da auch nicht aus aber wenn das done vom Thread aufgerufen wurde, dann kann es ja zu keinem Fehlverhalten kommen da der Thread dann ja nichts mehr macht. Es ist halt nur noch nicht abgeräumt.

Allerdings halte ich es auch für keine guten programmierstil wenn du ständig neue Threads erzeugst. Wenn du einen Thread immer wieder benutzt, dann solltest du ihn auch entsprechend wieder verwenden.

Gruß

Claus
 
Der Thread soll nur was machen nachdem ein entsprechender Button gedrückt wurde.
Das neue Erzeugen soll dann sicherstellen, das alle Attribute ihren Initial wert haben. Damit ich nicht jedes Attribut einzeln zurücksetzen muss.
 
Ist aber trotzdem keine saubere Programmierung.

Ohne genau zu wissen was du da machst klingt das für mich so als ob du einen Thread brauchst, der auf abruf eine Aktion durchläuft. Dass bedeutet du solltest eine Queue programmieren in die du deine anfordrung steckst und die der Thread dann abarbeitet.

Also der Main Thread added ein wie auch immer geartetes Objekt in eine List. Der Thread bekommt ein Start geschickt und holt sich das Objekt aus der List und bearbeitet es. Ist er damit fertig schaut er nach ob noch weiter Objekte in der Liste sind . Wenn ja dann arbeitet er solange ab bis die Liste leer ist und geht dann in Idle State und wartet auf das nächste Start Signal from Main Thread.

Gruß

Claus
 
Danke für den Vorschlag.

Der Swingworker ist über eine Queue mit einem Thread verbunden, der Daten über eine Socket-Verbindung empfängt und in die Queue ablegt.

Ich würde jetzt bei Stop. Über ein Flag in while-Schleife den Swingworker anhalten und die Socketverbindung schließen. Dadurch wird die Queue nicht weiter gefüllt und es kann deren Inhalt löschen und die restlichen Attribute neu initaliseren.
 
Ja. Also die Funktion innerhalb des SwingWorkers funktioniert.
Sobald ich aber diesen Beenden möchte und irgendwann später einen neuen erzeuge kommt es zu den o.g. Problemen

Ein "normaler" Thread von Runnable abgeleitet, verschwindet aus der Debug-Ansicht, wenn er beendet wird.
 
Zuletzt bearbeitet:
Wenn du deinen JTable (nicht) mehr fuellen willst, sobald ein Button gedrueckt worden ist, dann empfehle ich dir du benutzt kein Void, sondern etwas wie Vector (naja, zwar veraltet aber funktioniert noch), oder ArrayList.

Beispiel:
Java:
   @Override
    protected Vector doInBackground() throws Exception
    {         
        Vector row = new Vector();
         // do something lengthy
          if (isCancelled())
          {
                return row;
          }
          else
          {
                // Add rows
                Vector v = new Vector();
                v.add(false);
                // ... etc.
                publish(v);
          }
       return row;
    }
 
Mein Tabellenmodel benutzt eine ArrayList. Über Publish sende ich einzelne Objekte an process und Process übergibt wieder eine Liste dieser Objekte an das Model wo sie eingefügt werden

Ich werde deinen Vorschlag mal ausprobieren. Danke.
 
Das neue Problem was auftaucht, wenn ich den SwingWorker anhalte, blieben alte Daten im process() Parameter chunks. Diese Daten möchte ich aber gar nicht mehr im TabellenModel haben. Jetzt muss ich diese irgendwie löschen können ...
 
Das hat denke ich wenig mit dem SwingWorker zutun, sondern eher damit, dass du z.B. ein "Start" Button brauchst, und sofort im ActionListener dein JTable leeren sollst, bevor du es fuellst.
Beispiel:
Java:
startButton.addActionListener(new ActionListener()
{
       @Override
        public void actionPerformed(ActionEvent e)
        {
              DefaultTableModel dtm = (DefaultTableModel) meineTabelle.getModel();
              dtm.setRowCount(0);
              // alles andere kommt dannach..
         }
});
 
Das tue ich bereits. Habe ich aber nicht erwähnt. Sry.

Beim Start wird mein Modell geleert und anschließend der SwingWorker erzeugt und gestartet.

Das mit den chunks war ne falsche Vermutung von mir. Ich hatte noch Restdaten in enerlokalen Variable die nach Start noch verarbeitet wurden
 

Zurück
Oben