# Probleme mit GUI und Threads



## babuschka (14. Jun 2007)

Ich weis, dass hier schon recht viel zu dem Thema gepostet wurde, aber ich bin leider immer noch nicht schlauer. Ich stehe halt mit Threads schon lange auf Kriegsfuß. :cry:

Nun aber zu meinem Problem:
ich habe ein Fenster, dass nach einem Klick (und natürlich richtigen Einstellungen) eine 10MB große Datei herunterlädt um damit die Transferrate zu ermitteln.
Das funktioniert soweit auch schon, allerdings ist die GUI natürlich solange eingefroren. Deshalb habe ich eine ProgressBar eingebaut, und die zeitintensive Methode in einem andern Thread ausgelagert.
Ich versuche über wait() und notify() die Kommunikation der Threads zu regeln.

Leider bekomme ich immer eine IllegalMonitorStateException.

Hier ein Codeausschnitt:


```
//(...)
 
 private Object lock = new Object() ;
 
 //(...)
 
 //wird nach einem Buttonklick aufgerufen
 private void btnSubmitActionPerformed(java.awt.event.ActionEvent evt) {                                          
         
        verarbeitung_ref.server_file = txtServer.getText() ;
        
        //Thread starten
        SendWorker sw_ref = new SendWorker() ;
        sw_ref.start() ;
        
        
        //Submit - Button deaktivieren
        btnSubmit.setEnabled(false) ;
        
        //JProgressBar sichtbar machen
        prgBar.setVisible(true) ;
        
        prgBar.setIndeterminate(true) ;
            
        
        try 
        {
            Thread me = Thread.currentThread() ;

            synchronized(lock)
            {
                me.wait() ;
            }
        }

        catch (InterruptedException ex) 
        {
            ex.printStackTrace();
        }    
        
        //OHNE Threads: das wird benutzt wenn ich keine zusätl. Threads nehme
//        verarbeitung_ref.gesendet = verarbeitung_ref.send() ;
        
        prgBar.setIndeterminate(false) ;
        prgBar.setVisible(false) ;
        btnSubmit.setEnabled(true) ;
        
        //bei geglückter Ausführung von send
        if (verarbeitung_ref.gesendet)
        {
            lblStatus.setForeground(new Color (0, 0, 0)) ;
            lblStatus.setText("") ;
            lblStatus.setText(verarbeitung_ref.status) ;
            
        }
        
        //im Fehlerfall
        else
        {
           //weiterer Code
        }
        
       //(...) weitere Methode, speichert Ergebnisse in Datei
    }                                         

    class SendWorker extends Thread
    {
        public void run()
        {
            //dies ist eine Methode, die z.B ein 10MB große
            //Datei herunterlädt, dies dauert natürlich,
            //deswegen soll auch eine Progressbar angezeigt werden
            verarbeitung_ref.gesendet = verarbeitung_ref.send() ;

            synchronized(lock)
            {
                notify() ;
            }
        }
    }
    
    //(...)
```

Vielleicht kann mir jemand ein paar Tipps geben, oder ein paar Fehler aufdecken.
Vielen Dank schon mal!


----------



## Marco13 (14. Jun 2007)

Eine IllegalMonitorStateException, wenn man auf einem Objekt "wait" oder "notify" aufruft, auf dem man NICHT synchroniziert ist. Bei dir dürfte das bei

```
synchronized(lock)
{
   me.wait() ;
}
```
und

```
synchronized(lock)
{
   notify() ;
}
```
der Fall sein. Ohne den Code komplett nachvollzogen zu haben (zumindest den geposteten Teil des Codes :roll: ) : Mit

```
synchronized(lock)
{
   lock.wait() ;
}
```
und

```
synchronized(lock)
{
   lock.notify() ;
}
```
_KÖNNTE_ es funktionieren.


----------



## babuschka (14. Jun 2007)

Das habe ich probiert, mit dem Erfolg, dass das ganze sich nun wieder genauso verhält, wie ohne Threads  .
Ich weis auch nicht, ob das mit dem lock-object überhaupt sinnvoll ist, oder ob es auch anders geht.
Vielleicht kann man ja auch join benutzen. ???:L 

Ich weis auch nicht, warum mir das Thema so schwer fällt.

Vielen Dank aber für deine Antwort :toll: 

Jemand noch Ideen :?:


----------



## Marco13 (14. Jun 2007)

Habs jetzt nochmal _etwas_ genauer gelesen: Du blockierst (bzw. WILLST blockieren) den event-dispatch-thread. Der Ablauf war vorher

```
Im event dispatch thread
{
    btnSubmitActionPerformed
    {
        btnSubmit.setEnabled(false) ; 

        mache was aufwändiges

        btnSubmit.setEnabled(true) ;   
    }
}
```
und ist jetzt

```
Im event dispatch thread
{
    btnSubmitActionPerformed
    {
        btnSubmit.setEnabled(false) ; 

        Im eigenen thread
        {
            mache was aufwändiges
        }
        warte bis Thread fertig ist

        btnSubmit.setEnabled(true) ;   
    }
}
```
Was fast(!) auf's gleiche rauskommt. Stattdessen wäre der gewünschte Ablauf wohl

```
Im event dispatch thread
{
    btnSubmitActionPerformed
    {
        btnSubmit.setEnabled(false) ; 

        Im eigenen thread
        {
            mache was aufwändiges
            Im Event dispatch thread
            {
                btnSubmit.setEnabled(true) ;   
            }
        }
    }
}
```

Du solltest dir vmtl. mal die SwingWorker-Klasse ansehen, denn die ist genau dafür da.
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/worker.html

Ein Beispiel gibt's auch bei der API-Doku:
http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html

Wenn noch Fragen sind, sag' bescheid.


----------



## babuschka (15. Jun 2007)

Also ich habe folgendes gefunden:


```
final JLabel label;
   class MeaningOfLifeFinder extends SwingWorker<String, Object> {
       @Override
       public String doInBackground() {
           return findTheMeaningOfLife();
       }

       @Override
       protected void done() {
           try { 
               label.setText(get());
           } catch (Exception ignore) {
           }
       }
   }
 
   (new MeaningOfLifeFinder()).execute();
```

Das sieht schon mal recht vielversprechend aus! Erstmal Danke dafür :toll: 
Ich weis aber immer noch nicht genau, wie ich das Ganze dann implementieren soll.

Ich stelle mir das jetzt so vor:


```
//(...)

public String doInBackground()
{
     //tue was aufwendiges und gib was zurück
}
```

OK, aber was ist mit done() ?
Kann ich nicht einfach mit dem Hauptthread weiter machen?  ???:L 
Muss ich dann den ganzen restlichen Code der im Button-Ereignisshandler steht auch in done() packen?

Noch was anderes: Ich werde das jetzt höchstwahrscheinlich mit dem SwingWorker machen, aber wie mache ich das ohne? Interessiert mich nur, weil ich bald Prüfung schreibe und sich der Stoff auf Java 5 bezieht.[/img]

Ach Ja! Damit kann ich gar nichts anfangen: <, >
Wofür sind diese Klammern?


----------



## Marco13 (15. Jun 2007)

Hm - den SwingWorker gibt's erst seit Java 1.6, und wenn du fragst, wofür die < > Klammern sind, dann hast du das vmtl noch nicht? Die Klammern < > stehen für Generics, die mit Java 1.5 eingeführt wurden.

Bei "done" wird das gemacht, was NACH dem Abarbeiten des aufwändigen Teils gemacht werden soll. Bei dir wäre das: Die Butons wieder enablen.

Du kannst aber auch die Funktionalität den SwingWorkers für diesen speziellen Fall nachbauen - als Beispiel, mit einem Button, ungefähr so

```
class MyWorker implements Runnable
{
    private JButton button;
    public MyWorker(JButton b)
    {
        button = b;
    }

    public void run()
    {
        // Wird in eigenem Thread ausgeführt ("doInBackground")
        machwWasAufwändiges();

        
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run() // // Wird (nachher) im Event-Dispatch-Thread ausgeführt  (entspricht "done")
            {
                button.setEnabled(true);
            }
       });
    }
}

void actionPerformed(...)
{
    button.setEnabled(false);
    new Thread(new MyWorker()).start();
}
```
Der SwingWorker ist aber allgemeiner, und speziell für diesen Zweck gemacht...


----------



## babuschka (15. Jun 2007)

Ersteinmal Danke, dass du dir soviel Mühe machst. :applaus: 

Es ist so: Ich bin Informatikstudent und hatte 2 Semester Programmieren, allerdings basierend auf Java 1.4 .
Außerdem hatte ich ein Semester Parallele Systeme basierend auf 1.4 aber mit Hinweisen auf Java 5. Ich muss aber nicht umsonst 3. Prüfung in diesem Fach schreiben, Threads liegen mir halt nicht so ganz. Deswegen brauchte ich auch ne Alternative. Ich hoffe, dass der Groschen bald mal fällt.

Also,meine Anwendung besitzt die Klassen GUI (mit der Methode main, Eventhandlern und den Code, der fürs Fenster gebraucht wird) eine Klasse Verarbeitung, in welcher unter anderem die zeitaufwendige Methode steht) und einer weiteren Klasse, die einen Dialog bereitstellt.

Eigentlich wollte ich für den Thread auch ne neue Klasse erstellen, aber weis nicht, ob das sinnvoll ist.
Im Eventhandler des einen Buttons, wollte ich dann die Threadklasse (sollte eigentlich auch ne Klasse sein, die nicht von Thread erbt, sondern Runnable implementiert, hatte dann aber Pobleme mit den Threadmethoden) aufrufen, welche in ihrer run()-Methode die aufwendige Methode der Klasse Verarbeitung implementiert. Der boolean Rückgabewert dieser Methode wird in einer static Variablen in Verarbeitung gespeichert und später in Gui benutzt.

Der Thread in GUI sollte erst die Buttons disablen und ne Progressbar anzeigen, dann auf den anderen Thread warten und anschließend die Buttons wieder enablen und die Progressbar verschwinden lassen.

Ich checks einfach nicht :cry:


----------



## Marco13 (15. Jun 2007)

Dann beschreib' nochmal genauer, WAS jetzt nicht funktioniert, bzw. was du (von dem bisher geposteten Code) dort (aus welchem Grund) nicht einbauen kannst. Ideal wäre natürlich ein kleines, selbstständig compilierbares Beispiel, das aus den relevanten(!) Teilen des GUIs besteht, und wo der "aufwändige Task" vielleicht einfach durch eine for-(1 to 1000000000) Schleife ersetzt ist...


----------



## babuschka (15. Jun 2007)

Sorry, dass ich so spät antworte.

Also, ich habe jetzt folgenden Code:


```
private void btnSubmitActionPerformed(java.awt.event.ActionEvent evt) {                                          
        
        verarbeitung_ref.server_file = txtServer.getText() ;
        
        BackgroundWorker bgw_ref = new BackgroundWorker() ;
        bgw_ref.execute() ;
        bgw_ref.doInBackground() ;
        
        //Labels zurücksetzen (wichtig bei mehreren Tests)
        lblSaveStatus.setText("") ;
        lblStatus.setText("") ;
        
        //Submit - Button deaktivieren
        btnSubmit.setEnabled(false) ;
        
        //Proxy - Button deaktivieren
        btnProxySettings.setEnabled(false) ;
        
        //JProgressBar sichtbar machen und laufen lassen
        prgBar.setVisible(true) ; 
        prgBar.setIndeterminate(true) ;
        
        //Code in done ausführen
        bgw_ref.done() ;
    }                                         
    
    class BackgroundWorker extends SwingWorker<String, Void> 
    {
        @Override
        public String doInBackground() 
        {
            verarbeitung_ref.gesendet = verarbeitung_ref.send() ;
            return "" ;
        }

        @Override
        protected void done() 
        {
            try 
            {
                prgBar.setIndeterminate(false) ;
                prgBar.setVisible(false) ;
                btnSubmit.setEnabled(true) ;
                btnProxySettings.setEnabled(true) ;

                //bei geglückter Ausführung von send
                if (verarbeitung_ref.gesendet)
                {
                    lblStatus.setForeground(new Color (0, 0, 0)) ;
                    lblStatus.setText("") ;
                    lblStatus.setText(verarbeitung_ref.status) ;
                }

                //im Fehlerfall
                else
                {
                    lblStatus.setForeground(new Color (255, 0, 0)) ;
                    lblStatus.setText("") ;

                    //wenn die statische Variable status aus Verarbeitung leer ist,
                    //was bedeuted, dass ein unerwarteter Fehler aufgetreten ist
                    if(verarbeitung_ref.status.isEmpty())
                    {
                        lblStatus.setText("Error: An unexpected error occured! Please close the application!") ;
                    }

                    //ansonsten wird eine entsprechende Fehlermeldung ausgegeben
                    else
                    {
                        lblStatus.setText(verarbeitung_ref.status) ;
                    }
                }

                //createCSVFile
                if(chkSave.isSelected())
                {
                    //Speichern unter Dialog...
                    //...

                    verarbeitung_ref.createCSVFile() ;

                    if(verarbeitung_ref.savestatus.contains("failed"))
                    {
                        lblSaveStatus.setForeground(new Color(255,0,0)) ;
                        lblSaveStatus.setText(verarbeitung_ref.savestatus) ;
                    }

                    else
                    {
                        lblSaveStatus.setForeground(new Color(0,0,0)) ;
                        lblSaveStatus.setText(verarbeitung_ref.savestatus) ;
                    }
                }    
            }//endtry

            catch (Exception ex) 
            {
                ex.printStackTrace() ;
            }
        }//endmethod done
    }
```

Ich weis mit execute nichts richtig anzufangen. Weis auch nicht, wann ich es aufrufen soll.
Mit execute() kommt es teilw. zu offensichtlich falschen Ergebnissen, auch funktioniert die GUI nicht so, wie sie soll (die GUI hängt wie ohne Thread).
Ohne execute() sind die Ergebnisse richtig, aber die GUI hängt weiterhin.


Edit: Noch was vergessen: ich weis auch nicht, ob die Ausdrücke in <> richtig sind. Wollte eigentlich keinen String, aber der Compiler hat gemeckert, wenn ich das geändert habe! EditEnde :wink: 

Für Ideen bin ich weiterhin offen, werde aber auch selbst am WE, mir das mal zu Hause anschauen, und vielleicht ein einfacheres Programm schreiben, dass die Arbeit nur simuliert (also den Download).

Sobald ich was hab, poste ich es hier (werde heute aber wohl nicht mehr dazu kommen).

Vielen Dank nochmal (das kann man gar nicht oft genug sagen  )!


----------



## Marco13 (15. Jun 2007)

Auf jeden Fall darfst du doInBackground nicht direkt aufrufen. Du solltest NUR execute aufrufen müssen (doInBackground wird indirekt von execute aufgerufen)

Wenn du ein compilierbares Beispiel hast, sag nochmal bescheid.


----------



## babuschka (19. Jun 2007)

Tut mir leid, dass ich mich nicht mehr gemeldet habe. 
Bin leider noch nicht dazu gekommen, dass Programm zu schreiben.  
Soll mein Programm jetzt ohne Threads realisieren.

Werde aber dennoch an der Sache dran bleiben, allein schon wegen der Prüfung.
Da ich aber noch ein anderes Projekt habe, weis ich nicht, wann ich dazu komme.

Will es aber diese Woche noch schaffen.
Poste es hier, sobald ich es habe.


----------



## babuschka (20. Jun 2007)

*Bescheid sag*  :wink: 

Hab jetzt ein Progrämmchen geschrieben, dass auch funktioniert (zumindest in NetBeans).
War zu einfach um wahr zu sein, dank den vielen Tipps.
Auch done() wird wohl von execute aufgerufen.

Das Programm kann die Zukunft vorhersagen :wink:, 
solche Sachen hab ich schon irgenwo hinten links im Internet gesehen :lol: .

Ein Problemchen habe ich aber noch: Kann man den Thread in SwingWorker irgendwie unterbrechen? ???:L 
Denn wenn ich das Programm während es läuft schließe, wird es nicht ordnungsgemäß beendet.   

Vielen Dank :toll:  :toll:  :toll:  :applaus:


----------



## babuschka (20. Jun 2007)

Ach jetzt hab ich den Code ganz vergessen!  

Klassen Gui:

```
/*
 * Gui.java
 *
 * Created on 20. Juni 2007, 10:05
 */

package guitestpro;

import java.awt.* ;
import javax.swing.* ;

public class Gui extends javax.swing.JFrame 
{
    
    // <editor-fold defaultstate="collapsed" desc=" Variablen "> 
    Verarbeitung v_ref = new Verarbeitung() ;
    // </editor-fold> 
    
    // <editor-fold defaultstate="collapsed" desc=" Konstruktor ">
    /** Creates new form Gui */
    public Gui() {
        initComponents();
        pgbFortschritt.setVisible(false) ;
    }// </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">                          
    private void initComponents() {
        btnSchließen = new javax.swing.JButton();
        btnMyFuture = new javax.swing.JButton();
        lblFrage = new javax.swing.JLabel();
        txtFrage = new javax.swing.JTextField();
        pgbFortschritt = new javax.swing.JProgressBar();
        lblAntwort = new javax.swing.JLabel();
        txtAntwort = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        btnSchließen.setText("Schlie\u00dfen");
        btnSchließen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSchließenActionPerformed(evt);
            }
        });

        btnMyFuture.setText("My Future");
        btnMyFuture.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnMyFutureActionPerformed(evt);
            }
        });

        lblFrage.setText("Frage:");

        lblAntwort.setText("Antwort:");

        txtAntwort.setEditable(false);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(21, 21, 21)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(lblAntwort)
                            .addComponent(lblFrage)))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(btnSchließen)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(pgbFortschritt, javax.swing.GroupLayout.DEFAULT_SIZE, 258, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btnMyFuture))
                    .addComponent(txtAntwort, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 345, Short.MAX_VALUE)
                    .addComponent(txtFrage, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 345, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtFrage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblFrage))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(txtAntwort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblAntwort))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(btnMyFuture)
                    .addComponent(pgbFortschritt, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(btnSchließen))
                .addContainerGap())
        );
        pack();
    }// </editor-fold>                        

    // <editor-fold defaultstate="collapsed" desc=" Event Handler "> 
    private void btnSchließenActionPerformed(java.awt.event.ActionEvent evt) {                                             
        setVisible(false) ;
        dispose() ;
    }                                            

    private void btnMyFutureActionPerformed(java.awt.event.ActionEvent evt) {                                            
        
        v_ref.question = txtFrage.getText() ;
        
        BackgroundWorker bgw_ref = new BackgroundWorker () ;
        
        pgbFortschritt.setVisible(true) ;
        pgbFortschritt.setIndeterminate(true) ;
        
        bgw_ref.execute() ;
        
        
    }                                           
    // </editor-fold> 
    
    // <editor-fold defaultstate="collapsed" desc=" BackgroundWorker "> 
    class BackgroundWorker extends SwingWorker<String, Void>
    {
        @Override
        public String doInBackground()
        {
            if(v_ref.lookInFuture())
                {
                    int command = (int) (Math.random() * 3) ;
            
                    switch(command)
                    {
                        case 0:
                            txtAntwort.setText("Ja, davon kannst du ausgehen!");
                            break ;
                    
                        case 1:
                            txtAntwort.setText("Ja, gut möglich!") ;
                            break ;
                    
                        case 2:
                            txtAntwort.setText("Klaro!") ;
                            break ;
                    
                        default:
                            txtAntwort.setText("Was weis ich !?") ;
                    }
                }
        
                else
                {
                    int command = (int) (Math.random() * 3) ;

                    switch(command)
                    {
                        case 0:
                            txtAntwort.setText("Nein, unmöglich!");
                            break ;

                        case 1:
                            txtAntwort.setText("Ääääääh, nein!") ;
                            break ;

                        case 2:
                            txtAntwort.setText("Iie! (Nein!)") ;
                            break ;

                        default:
                            txtAntwort.setText("Was weis ich !?") ;
                    }
                }
            return "" ;
        }

        @Override
        protected void done()
        {
            try
            {
                pgbFortschritt.setIndeterminate(false) ;
                pgbFortschritt.setVisible(false) ;
            }//endtry

            catch (Exception ex)
            {
                ex.printStackTrace() ;
            }
        }//endmethod done
    }// </editor-fold> 
    
    // <editor-fold defaultstate="collapsed" desc=" main "> 
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new Gui().setVisible(true);
            }
        });
    }// </editor-fold> 
    
    // <editor-fold defaultstate="collapsed" desc=" Generated Variables "> 
    // Variables declaration - do not modify                     
    private javax.swing.JButton btnMyFuture;
    private javax.swing.JButton btnSchließen;
    private javax.swing.JLabel lblAntwort;
    private javax.swing.JLabel lblFrage;
    private javax.swing.JProgressBar pgbFortschritt;
    private javax.swing.JTextField txtAntwort;
    private javax.swing.JTextField txtFrage;
    // End of variables declaration                   
    // </editor-fold>     
}
```

Und die Klasse Verarbeitung:

```
package guitestpro;

public class Verarbeitung 
{    
    protected static String question = "" ;
    
    /** Creates a new instance of Verarbeitung */
    public Verarbeitung() 
    {
        
    }
    
    public boolean lookInFuture()
    {
      
        if (question.toCharArray().length % 2 == 0)
        {
            //natürlich dauert es ein wenig, um in die Zukunft zu schauen ;-)
            for(int i = 0; i < 10000000; i++)
            {
                //ich sehe, ich sehe...
                int result = (int) Math.pow(i * i / 42 * i, i);
            }
            return true ;
        }

        else
        {
            //natürlich dauert es ein wenig, um in die Zukunft zu schauen ;-)
            for(int i = 0; i < 10000000; i++)
            {
                //ich sehe, ich sehe...
                int result = (int) Math.pow(i * i / 42 * i, i);
            }
            return false ;
        } 
    }
}
```


----------



## Marco13 (20. Jun 2007)

Die Schleife, die du verwendest, um ein bißchen Zeit verstreichen zu lassen, könntest du durch ein

```
try
{
int ms = (int)(Math.random()*3000);
Thread.sleep(ms);
}
catch (InterruptedException e)
{
}
```
ersetzen. Ich glaube, der Thread müßte dann beim Programmende automatisch interrupted werden. Wenn nicht, kann man das vmtl. irgendwie von Hand machen (müßte ich aber auch erstmal in der SwingWorker-Doku nachlesen)


----------



## babuschka (20. Jun 2007)

Also, ich habe jetzt BackgroundWorker bgw_ref global initialisiert und im EventHandler des Schließen-Buttons folgendes geschrieben:

```
private void btnSchließenActionPerformed(java.awt.event.ActionEvent evt) {                                             
        bgw_ref.cancel(true) ;
        setVisible(false) ;
        dispose() ;
    }
```

Scheint zu funktionieren.

Die Sleep-Methode kann ich vielleicht hier anwenden, aber das macht ja im ursprünglichen Programm keinen Sinn, weil dort ja tatsächlich etwas getan wird (und der Thread eben im Running-Status bleibt).

Nochmals vielen Dank für deine Hilfe! :toll: :applaus:
Ich close das jetzt mal!


----------



## babuschka (20. Jun 2007)

:cry:  :cry:  :cry:  *Thema wieder aufmach*  :cry:  :cry:  :cry: 

Tja leider zu früh gefreut!
Das mit cancel() funktioniert so nicht. Habs bemerkt, als ich das in das eigentliche Programm eingebaut habe! :x 

Der Thread läuft immer noch solange weiter, bis er fertig ist.
Ein Klick auf den Close-Button soll den Thread aber beenden!

Weis jemand da was?


----------



## Marco13 (20. Jun 2007)

Grundsätzlich, und ohne genau zu wissen, was der Thread macht: Du kannst, während der Thread beschäftigt ist, abfragen, ob er Interrupted wurde
if (thisThread.isInterrupted()) return;
und bei einem Klick auf den Schließen-Button den Thread dann mit 
thread.interrupt();
killen, aber wie man das auf den SwingWorker überträgt, müßte ich, wie gesagt, erst nachlesen.


----------



## babuschka (21. Jun 2007)

Also cancel bewirkt anscheinend, dass der Thread in doInBackground abgebrochen wird, und dann die done()-Methode aufgerufen wird.
Bei mir scheint das Problem allerdings daran zu liegen, dass ich meinen Scanner mit der Methode next nicht abbrechen kann, der den Text liest, der beim Download angezeigt wird. :?
Das alles zu erklären würde sehr weit führen, aber beim meinem Beispiel ist es ja auch so, dass die for-Schleife nicht abgebrochen wird, sondern auch nach Schließen des Fensters erst fertig rechnet.
Vielleicht finde ich ja auch noch Einstellungen in dem Programm, dass ich zum Download benutze, der den Download einfach nach einer gewissen Zeit abbricht.  :###


----------

