# invokeLater - Wann?



## taouri (1. Dez 2006)

Hallo zusammen,

könnte mir bitte mal jemand erklären, wann genau man invokeLater (oder auch invokeAndWait) wirklich einsetzen muss. Ich habs leider noch immer nicht begriffen, trotz vielem Java-Tutorial lesen. Auch die Java Insel konnte mir nicht weiterhelfen. Muss ich z.B. generell in einem Eventhandler invokeLater benutzen, oder jedesmal wenn ich die GUI anspreche? Welche Befehle kann man zusammen in einen Thread hauen? Wann brauche ich einen einzelnen?

Ich hoffe jemand kann mir helfen

Gruß

taouri


----------



## Wildcard (1. Dez 2006)

Swing ist nicht threadsicher (mit ausnahme des repaint() aufrufs).
Wann immer ein Thread (der nicht der EventDispatcher Thread ist) also direkt oder indirekt(indirekt heißt zB du fügst Daten in ein Model ein, das daraufhin die GUI updatet) die GUI verändert, muss diese Veränderung mit dem EventDispatcherThread synchronisiert werden -> invokeLater


----------



## Gast (1. Dez 2006)

also auch zb. slider.setValue(2); ?


----------



## Wildcard (1. Dez 2006)

Wenn das nicht aus dem EventDispatcher passiert, ja.


----------



## Leroy42 (1. Dez 2006)

```
public void actionPerformed(ActionEvent e) {
  // Hier kann direkt die GUI angesprochen werden,
  // da alles was hier steht im EDT ausgeführt wird.

  new Thread(new Runnable() {
    public void run() {
      // Hier [i]sollte[/i] die GUI mit invokeLater angesprochen werden
      // Allerdings gibt es auch viele Thread-sichere Operationen wie
      // textField.setText("..."), ...
    }}).start();
}
```


----------



## Wildcard (1. Dez 2006)

Leroy42 hat gesagt.:
			
		

> // Allerdings gibt es auch viele Thread-sichere Operationen wie textField.setText("..."), ...


Im Zweifelsfall immer den Weg über invokeLater gehen


----------



## Leroy42 (1. Dez 2006)

Wildcard hat gesagt.:
			
		

> Im Zweifelsfall immer den Weg über invokeLater gehen



Was sind denn die Zweifelsfälle?
Oder anders gefragt: Ist es aus der API ersichtlich ob eine Methode _Swing-sicher_ ist.

Ich verfahre hierbei, entgegen meiner sonstigen Einstellung, ganz pragmatisch.

Solange ich nichts _merkwürdiges_ bemerke, heb' ich mir
invokeLater-Aufrufe für _schlechte Zeiten_ auf.


----------



## Wildcard (1. Dez 2006)

Leroy42 hat gesagt.:
			
		

> Was sind denn die Zweifelsfälle?


Liegt wohl im Sinne des Betrachters. Ich lese mir nicht die API jeder mir grundsätzlich bekannten Methode durch bevor ich sie benutze. Lieber etwas in invokeLater was auch so funktionieren würde als andersrum.
Der Fehlerfall ist bei Threads nunmal schwer reproduzierbar und hat die Eigenart prinzipiell nur beim Kunden oder Präsentationen aufzutreten  :autsch:


----------



## Leroy42 (1. Dez 2006)

Wildcard hat gesagt.:
			
		

> Der Fehlerfall ist bei Threads nunmal schwer reproduzierbar und hat die Eigenart prinzipiell nur beim Kunden oder Präsentationen aufzutreten  :autsch:



Naja, da muß ich dir Recht geben...


----------



## taouri (1. Dez 2006)

Oje... Wenn man nur mal wüsste, wieviel man Threadsicher machen muss BEVOR man ne GUI programmiert. Das wird ne Menge Arbeit fürcht ich. Meine GUI hat nämlich die unangenehme Angwohnheit auf Knopfdruck abzustürzen. Jetzt kommt aber das interessante:

Ich habe zwei Wege programmiert:

1. Ein Methodenaufruf, der durch einen Befehl über die Konsole ausgeführt wird.
2. Ein Knopf, der einen ActionListener besitzt, der durch invokeLater geschützt, die Methode aufruft, also eigentlich Thread-sicher ist.

Der Witz ist, Weg eins funktioniert, während bei der anderen Der Knopf gedrückt bleibt und sich die GUI bis zum St. Nimmerleinstag verabschiedet. Ich wüsste nur gern, wie man dieses Phänomen erklären will... Jemand ne Idee?

Gruß

taouri


----------



## Wildcard (1. Dez 2006)

Das synchronisieren ist nicht weiter tragisch, da man in aller Regel nur sehr wenige Worker Threads braucht, die oft auch nur eine Aktion ausführen bevor sie beendet werden.
Zu deinem Problem: da bräuchte ich schon Code.


----------



## taouri (1. Dez 2006)

Das Problem is, dass ich leider nicht genau sagen kann wos dran liegt, und da es wirklich ein größeres Programm ist, in dem sehr viel auf die GUI zugegriffen wird, müsste ich schon so an die 600 Zeilen Code hier rein schreiben. Ich glaube das sprengt den Rahmen. Ich werd jetzt mal (bzw. Morgen *gähn*) versuchen das ganze generell abzusichern.

Gruß

taouri


----------



## byte (2. Dez 2006)

Aus diesem Grund ist es sinnvoll, nach dem MVC Prinzip zu trennen. Wenn Du genau einen (oder wenige) Punkte hast, an denen die GUI aktualisiert wirst, dann behälst Du auch leichter den Überblick über Deinen Entwurf.


----------



## Guest (2. Dez 2006)

Das Problem is nur, dass ich sone Art eigene Canvas geschreiben hab, die nunmal leider ziemlich oft auf sich selbst zugreift. Diese Zugriffe kann ich nicht minimieren. Von außen sind es gar nicht so viele Zugriffe.


----------



## byte (2. Dez 2006)

Ein Canvas, das sich selbst über einen zweiten Thread aktualisiert? ???:L


----------



## taouri (2. Dez 2006)

Naja, über diverse Listener halt. Die müssen aber, um mit der GUI zu kommunizieren, Methoden dieser aufrufen.


----------



## becksdasflenst (30. Dez 2006)

Leroy42 hat gesagt.:
			
		

> ```
> public void actionPerformed(ActionEvent e) {
> // Hier kann direkt die GUI angesprochen werden,
> // da alles was hier steht im EDT ausgeführt wird.
> ...



tach, gesell ich mich ma hier dazu...

wie sprech ich denn das GUI mit invokelater in der run an? invokeLater() will ja ne runnable als parameter. da kommt dann this rein oder wie?

Mein Problem:
hab ne JList mit einträgen die ausm vector kommen. jetzt add ich dem vector dynamisch per knopfdruck weitere einträge, die aber nicht sichtbar werden, allerdings ergeben konsolenausgaben das die einträge korrekt im vector gelandet sind...

Die Lösung: invokeLater (anscheinend...  aber ich bekomms nich gebacken... das was ich an einträgen ändere muss in die run methode oder wie?


----------



## taouri (6. Jan 2007)

Hi,

Ich kann dir zwar nicht sagen, wie's genau richtig gemacht wird, aber ich denke mit this hättest du einige Probleme. Wenn du nämlich in der run()-Methode den invokeLater auf das Runnable der gerade laufenden run() legst, dann müsste das, soweit ich das richtig sehe, dazu führen, dass du in einer Endlosschleife landest:


```
Runnable<-------------------|
   -> run()                 |
       -> invokeLater(this)-|
```

Also: 

der Thread, der eigentlich das Runnable darstellt, wird mit start() gestartet. Damit läuft dessen run() - Methode an. die run()-Methode wiederum ruft per invokeLater ein Event in den EDT. Dieses wird abgearbeitet, was darin resultiert, dass die run()-Methode erneut anläuft und wieder invokeLater aufgerufen wird, usw.
Sollte es falsch sein. möge mich jemand korrigieren.

Für dein Problem fällt mir jetzt aber noch ein ähnliches von mir ein, das mit einem JTree funktionierte. Auf den habe ich dann einfach updateUI() gemacht und es hat funktioniert. Zwar sollte diese Methode etwas völlig anderes machen (nämlich das Look and Feel updaten) aber bei mir hat es dazu geführt, dass die Einträge sichtbar wurden.


Gruß

taouri


----------



## byte (6. Jan 2007)

```
// irgendwo in einem anderen Thread

SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    // GUI aktualisieren
  }
});
```


----------



## L-ectron-X (25. Jan 2007)

Ich habe dazu noch folgenden Beitrag gefunden:
http://java.sun.com/developer/technicalArticles/javase/swingworker/


----------



## Marco13 (25. Jan 2007)

Zweifelfälle gibt es eigentlich keine. (Im Zweifelsfall ist der Zweifelsfall nicht ThreadSafe). Eigentlich steht es in der Api-Doku immer explizit dabei, wenn eine Methode Threadsafe ist
Bsp.
http://java.sun.com/javase/6/docs/api/javax/swing/text/JTextComponent.html#setText(java.lang.String)

Edit: Ach so, das war ein alter Thread, der wieder hochgepoppt ist. Hab ich übersehen.  :roll:


----------



## Oni (13. Sep 2007)

Ich muss das Thema noch mal aufgreifen, weil ich mir da bisschen unsicher bin.

Folgende Situation:

Ich habe ein DatenModel mit Getter- und Setter-Methoden. Mein GUI greift auf das Model zu um Daten anzuzeigen. 
z.B. Button wird geklickt Daten gelesen und angezeigt.
Das Model befülle ich zum Teil (nicht immer) in einem separaten Thread, die Daten kommen aus einer Datenbank und es kann einen paar sekunden dauern bis die geladen sind. Muss ich dann das Model auch über invokeLater befüllen? oder reicht es wenn ich die Setter- und Getter synchronized mache?

Gruß Oni


----------



## Gast (15. Sep 2007)

keiner eine antwort zu der frage?


----------



## Gast (16. Sep 2007)

Ich sicher nicht, aber ich hab noch ne Frage:

Ich hab mir über invokelater bisher nie viele gedanken gemacht, ich hab immer nur den Konstruktor meines GUI über invokelater aufgerufen...

Wenn ich das jetzt hier richtig verstehe muss ich jede Methode über invokelater aufrufen die etwas an meinem GUI ändert (Component hinzufügt, löscht, updated, sliderwerte verändert, etc, außer repaint()) ist das korrekt?


----------



## merlin2 (16. Sep 2007)

Ja, das ist korrekt, wenn du es richtig verstehst.
Andernfalls nicht. (  ) :wink:


----------



## tim247 (16. Sep 2007)

Gast hat gesagt.:
			
		

> Wenn ich das jetzt hier richtig verstehe muss ich jede Methode über invokelater aufrufen die etwas an meinem GUI ändert (Component hinzufügt, löscht, updated, sliderwerte verändert, etc, außer repaint()) ist das korrekt?



aber nur aus einem separaten thread oder? wenn ich ohne zusätzliche threads arbeite, oder die das GUI nicht verändern braucht ich weder invokeLater noch invokeAndWait oder?


----------



## Beni (16. Sep 2007)

tim247 hat gesagt.:
			
		

> Gast hat gesagt.:
> 
> 
> 
> ...


Ja


----------



## tim247 (16. Sep 2007)

gut, danke


----------



## otto (17. Sep 2007)

Muss man auch für Erzeugung eines JDialogs invokeLater verrwenden?


----------



## otto (20. Sep 2007)

Eher nein, oder?


----------

