Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Asyncrone GUI

0 views
Skip to first unread message

Torsten Kunkel

unread,
Feb 5, 2006, 12:15:45 PM2/5/06
to
Hi,

ich weiß seltsame Überschrift, aber was besseres ist mir nicht
eingefallen...
Es geht um folgendes, ich habe eine Anwendung die auf Knopfdruck einen
Bitte-Warten-Bildschirm anzeigen soll und dann eine Berechnung
ausführt, danach soll der Bildschirm ausgeblendet werden.
Ist ja überhaupt kein Problem:

public class GUI {
private WaitingDialog waitingDialog;
public GUI() {
waitingDialog = new WaitingDialog();
}
public void showWaitDialog() {
waitingDialog.display();
}
public void hideWaitDialog() {
waitingDialog.setVisible(false);
}
}


public class SchnellerDialog {
public static void main(String[] args) {
GUI gui = new GUI();
gui.showWaitDialog();
gui.hideWaitDialog();
}
public void init() {
}
}

import javax.swing.JFrame;
class WaitingDialog extends JFrame {
public WaitingDialog() {
}
public void display() {
this.setVisible(true);
}
}


In diesem Beispiel geht das auch fantastisch.
Aber wenn ich das ganze aus meiner GUI aufrufe, dann geschieht
seltsames.
Ich rufe das show auf berechne etwas und blende es dann aus. Aber
genau das Ausblenden klappt nicht. Jedesmal wenn die Berechnung sehr
schnell ist (oder wegen Schaltern nicht stattfindet) ist der Dialog
hinterher noch sichtbar.
Bauei ch einen Thread.sleep(100) ein, dann reicht das schon um das
Problem zu beheben.

Ich vermute das hier eine Asyncronität entsteht, die Gui-Routinen vom
JDK bekommen gesagt "hey zeig mal an" und dann fast gleichzeitig
"blende mal aus", doch irgendwodurch wird wohl das ausblenden
ausgeführt noch bevor die Anzeige komplett ist.
Das ist aber nur eine Spekulation.

Worum es mir nun geht ist, wie bitte kann ich das denn umgehen? Ich
kann doch nicht überall wo ich sowas habe einen Thread.sleep einbauen,
am liebsten hätte ich sowas wie gui.flush(); wo er dann erstmal wartet
bis alle GUI-Operationen auch vom Betriebsystem beendet wurden.

Ich weiß das das Problem schwer nachzuvollziehen ist, weil mein
Beispiel oben nicht "klappt", und das ist auch so ein Punkt den ich
nicht verstehe, denn es ist eigentlich exakt das was ich in der GUI
mache.

Achso, bevor die Frage kommt, das display habe ich drin statt direkt
setVisieble(true) aufzurufen um später noch sachen wie zenrierung oder
ähnliches einzubauen, das problem tritt aber auch mit direktem
setvisible(true) auf.

Ich habe das ganze unter Linux laufen mit dem JDK 1.5.0_02.

Hat jemand soetwas schon einmal gehabt?

Gruß

Torsten

Kurt Harders

unread,
Feb 5, 2006, 12:44:58 PM2/5/06
to
Hallo Torsten,

Torsten Kunkel wrote:

> Es geht um folgendes, ich habe eine Anwendung die auf Knopfdruck einen
> Bitte-Warten-Bildschirm anzeigen soll und dann eine Berechnung
> ausführt, danach soll der Bildschirm ausgeblendet werden.
> Ist ja überhaupt kein Problem:

Aber schon nicht ganz korrekt :-).


>
> public class GUI {
> private WaitingDialog waitingDialog;
> public GUI() {
> waitingDialog = new WaitingDialog();
> }
> public void showWaitDialog() {
> waitingDialog.display();
> }
> public void hideWaitDialog() {
> waitingDialog.setVisible(false);
> }
> }
>
>
> public class SchnellerDialog {
> public static void main(String[] args) {
> GUI gui = new GUI();
> gui.showWaitDialog();
> gui.hideWaitDialog();
> }
> public void init() {
> }
> }
>
> import javax.swing.JFrame;
> class WaitingDialog extends JFrame {
> public WaitingDialog() {
> }
> public void display() {
> this.setVisible(true);
> }
> }
>

Alle Aktionen auf die GUI sollen laut Sun nur im Event Handling Thrwad
erfolgen. Also musst Du ALLE API-Aufrufe von Swing-Objekten in
SwingUtilities.invokeLater kapseln.

Gruß, Kurt

--
Kurt Harders
PiN -Präsenz im Netz GITmbH
mailto:ne...@kurt-harders.de
http://www.pin-gmbh.com

Bernd Eckenfels

unread,
Feb 5, 2006, 12:46:44 PM2/5/06
to
Kurt Harders <ne...@kurt-harders.de> wrote:
> Alle Aktionen auf die GUI sollen laut Sun nur im Event Handling Thrwad
> erfolgen.

Wo steht das eigentlich.

Gruss
Bernd

Bernd Eckenfels

unread,
Feb 5, 2006, 12:51:24 PM2/5/06
to
Bernd Eckenfels <be-n...@lina.inka.de> wrote:
> Wo steht das eigentlich.

Gefunden: http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html#EDT

Insbesndere die Bemerkung zum "not realized" laesst einen zwar ein wenig
zweifeln dass die Leute bei Sun wissen was sie tun, aber umso mehr Grund
sich an die Vorgabe zu halten .) (Womit Swing aber endgültig aussterben
wird:)

Gruss
Bernd

Michael Rauscher

unread,
Feb 5, 2006, 1:12:32 PM2/5/06
to
Bernd Eckenfels schrieb:

> Bernd Eckenfels <be-n...@lina.inka.de> wrote:
>
>>Wo steht das eigentlich.
>
>
> Gefunden: http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html#EDT
>
> Insbesndere die Bemerkung zum "not realized" laesst einen zwar ein wenig
> zweifeln dass die Leute bei Sun wissen was sie tun, aber umso mehr Grund
> sich an die Vorgabe zu halten .)

Die entsprechende Aussage von Sun hat mich allerdings auch schon stutzig
gemacht. Ich vermute, dass die Schreiberlinge des Tutorials einem Bug
aufgesessen haben, der jedoch nicht in Kürze (im Fall von Sun also
innerhalb der nächsten zehn Jahre :-) ) behoben wird. Ein Workaround ist
leicht ins Tutorial geschrieben...

> (Womit Swing aber endgültig aussterben
> wird:)

Naja. Warum sollte es?

Gruß
Michael

Torsten Kunkel

unread,
Feb 5, 2006, 1:22:28 PM2/5/06
to
Hi,

Kurt Harders <ne...@kurt-harders.de> wrote:
> Alle Aktionen auf die GUI sollen laut Sun nur im Event Handling Thrwad
> erfolgen. Also musst Du ALLE API-Aufrufe von Swing-Objekten in
> SwingUtilities.invokeLater kapseln.

Danke für den Hinweis, aber, verzeih, wie krank is das bitteschön?
Das bedeutet doch, dass ich nun bei jeder Aktion

Runnable show = new Runnable() {
public void run() { meinDialog.setVisible(true); }
};
SwingUtilities.invokeLater(show);

drumpacken muß, und das nur weil ich eine saubere Trennung zwischen
Client und GUI haben wollte.

Ich finde die hätten das auch eleganter lösen können, halt sowas wie
"dialog.setSyncron(true)" oder sowas in der Art.

Danke auf alle fälle für den Hinweis :)

Gruß

Torsten

Michael Hüttermann

unread,
Feb 5, 2006, 4:19:04 PM2/5/06
to

Torsten Kunkel schrieb:

wenn du dich zur zeit im EDT befindest musst du es nicht machen.

Michael

Karsten Lentzsch

unread,
Feb 5, 2006, 4:56:57 PM2/5/06
to
Torsten Kunkel schrieb:

> ich weiß seltsame Überschrift, aber was besseres ist mir nicht
> eingefallen...

Sun erklärt in drei Artikeln das Wichtigste zu Threads in Swing:
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

Dort steht, wann einfache Sachen einfach gehen (alles im EDT),
wann man bei Hintergrundarbeiten in den EDT gehen muss
und zeigt drei Varianten zum Wechsel aus-in den EDT:
#invokeLater, #invokeAndWait und den SwingWorker.

Alternativen findet man bei Spin, Foxtrot und
nun im Java 6 SwingWorker, den es auch als
Java 5-Backport gibt.

-Karsten

Karsten Lentzsch

unread,
Feb 5, 2006, 5:00:20 PM2/5/06
to
Michael Rauscher schrieb:

> Die entsprechende Aussage von Sun hat mich allerdings auch schon stutzig
> gemacht. Ich vermute, dass die Schreiberlinge des Tutorials einem Bug
> aufgesessen haben, der jedoch nicht in Kürze (im Fall von Sun also
> innerhalb der nächsten zehn Jahre :-) ) behoben wird. Ein Workaround ist
> leicht ins Tutorial geschrieben...

Ich weiß nicht genau, worauf Du Dich beziehst,
aber Kathy Walrath hat Swing und Threads verstanden.
Sie ist auch nicht einem Bug aufgesessen.

In den neueren Versionen des Swing-Tutorials
wird eben gezeigt, wie man Thread-Probleme
beim Anwendungsstart leicht vermeiden kann;
es gibt wie immer andere Wege diese Probleme
zu meiden.

-Karsten

Wanja Gayk

unread,
Feb 5, 2006, 6:07:18 PM2/5/06
to
ne...@tkunkel.de said...

[..]


> In diesem Beispiel geht das auch fantastisch.
> Aber wenn ich das ganze aus meiner GUI aufrufe, dann geschieht
> seltsames.
> Ich rufe das show auf berechne etwas und blende es dann aus. Aber
> genau das Ausblenden klappt nicht.

[..]

Das Problem:
Events aus der GUI werden im sogenannten EDT (Event Dispatching Thread)
abgearbeitet. Der EDT dispatched aber nicht nur Events, sondern er malt
auich die GUI neu.
Wenn du also gerade ein Event im EDT abarbeitest, kannst du
währenddessen nicht die GUI neu zeichnen lassen, weil du den EDT ja noch
beschäftigst.

Died Lösung:
Behandle deine Sachenm, die länger dauern sollen in einem eigenen Tread,
und Ändreungen, die sich an der GUI ergeben, schickst du per
SwingUtilities.invokeLater wieder in den EDT.

Ich habe dazu eine recht passable Hilfsklasse, die "JobQueue" gebaut
(Quelltext folgt).

Man benutzt sie so:

class MyClass implements ActionListener{

private final JobQueue JOB_QUEUE = new JobQueue("Non-EDT-Dispatcher");

//[..]

public void actionPerformed(final ActionEvent e){
JOB_QUEUE.enqueue(new Runnable(){
public void run(){
SwingUtilities.invokeLater(new Runable(){
public void run(){
showAProgressBarOrSimilar();
}
});

doSomethingThatTakesVeryLong();

SwingUtilities.invokeLater(new Runable(){
public void run(){
hideAProgressBarOrSimilar();
}
});
}
});
}
}


Der Code für die JobQueue ist einfach:

package de.plush.brix.common;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
* Executes jobs in a single thread.<BR>
* Every JobQueue queues its jobs in its own dispatching {@linkplain
java.lang.Thread Thread}, this ensures that the
* jobs executed using instances of this class do not block the GUI
(because they are not on the EDT) and are executed in
* FIFO-order.<BR>
* @author Wanja Gayk
*/
public class JobQueue extends Thread {
private final List<Runnable> enqueuedJobs =
Collections.synchronizedList(new LinkedList<Runnable>());

/**
* Creates and starts a new JobQueue.
*/
public JobQueue(final String name) {
super(name);
start();
}

/**
* Enqueues a Job to be executed.
* @param job the job to be executed.
*/
public synchronized void enqueue(final Runnable job) {
enqueuedJobs.add(job);
notifyAll();
}

/**
* @inheritDoc
* @see java.lang.Runnable#run()
*/
@Override
public final void run() {
while (!interrupted()) {
try {
while (enqueuedJobs.size() == 0) {
synchronized (this) {
wait();
}
}
final Runnable job = enqueuedJobs.remove(0);
job.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

/**
* @inheritDoc
* @see java.lang.Object#finalize()
* @throws Throwable if anything goes wrong
*/
@Override
public void finalize() throws Throwable {
interrupt();
super.finalize();
}
}


Ich hoffe das hilft dir weiter.

Gruß,
-Wanja-

--
"Gewisse Schriftsteller sagen von ihren Werken immer: 'Mein Buch, mein
Kommentar, meine Geschichte'. [..] Es wäre besser, wenn sie sagten:
'unser Buch, unser Kommentar, unsere Geschichte'; wenn man bedenkt, dass
das Gute darin mehr von anderen ist als von ihnen." [Blaise Pascal]

Michael Rauscher

unread,
Feb 5, 2006, 6:44:25 PM2/5/06
to
Karsten Lentzsch schrieb:

> Michael Rauscher schrieb:
>
>> Die entsprechende Aussage von Sun hat mich allerdings auch schon
>> stutzig gemacht. Ich vermute, dass die Schreiberlinge des Tutorials
>> einem Bug aufgesessen haben, der jedoch nicht in Kürze (im Fall von
>> Sun also innerhalb der nächsten zehn Jahre :-) ) behoben wird. Ein
>> Workaround ist leicht ins Tutorial geschrieben...
>
>
> Ich weiß nicht genau, worauf Du Dich beziehst,
> aber Kathy Walrath hat Swing und Threads verstanden.
> Sie ist auch nicht einem Bug aufgesessen.

Bezogen habe ich mich auf folgenden Absatz:

Note: We used to say that you could create the GUI on the main thread as
long as you didn't modify components that had already been realized.
[PENDING: The following red text belongs in a footnote.] Realized means
that the component has been painted onscreen, or is ready to be painted.
The methods setVisible(true) and pack cause a window to be realized,
which in turn causes the components it contains to be realized. While
this worked for most applications, in certain situations it could cause
problems. Out of all the demos in the Swing Tutorial, we encountered a
problem only in ComponentEventDemo. In that case, sometimes when you
launched the demo, it would not come up because it would deadlock when
updating the text area if the text area had not yet been realized, while
other times it would come up without incident.

Mit meiner Vermutung mag ich daneben liegen (daher "Vermutung"). Ich
weiß aber nicht, wie Du darauf kommst, ich würde annehmen, Kathy Walrath
(oder wer auch immer) hätte Swing und/oder Threads nicht verstanden.

Tatsache ist, dass ein Fehler dahintersteckt. Ob dieser nun in der
Aussage "you could create the GUI on the main thread as long as you
didn't modify components that had already been realized", im
dazugehörigen ComponentEventDemo oder in den "Tiefen" von AWT/Swing, sei
mal dahingestellt.

Allerdings gibt o. g. Absatz auch keine Auskunft darüber. Es steht zwar
da, was offensichtlich ist, nämlich dass die Anwendung nicht
"hochkommt". Es steht auch da, dass und an welcher Stelle ein Deadlock
entsteht. Aber über den Grund des Ganzen schweigt man sich aus. Auch
lässt man offen, ob es sich nun um einen Bug handelt oder ob es ein
Problem ist, das sich aus technischen/konzeptionellen Gründen nicht
beseitigen lässt.

Es wird dort auch nur schwammig von "meisten Anwendugen", "bestimmten
Situationen" und "kann sein, muss aber nicht" geschrieben.

Was soll man davon halten?

Gruß
Michael

Bernd Eckenfels

unread,
Feb 5, 2006, 8:23:46 PM2/5/06
to
Karsten Lentzsch <kar...@jgoodies.com> wrote:
> Ich weiß nicht genau, worauf Du Dich beziehst,

Wir beziehen uns auf die Aussage, dass man nicht-realisierte Swing Objekte
eigentlich auch in einem anderen Thread (z.b. main) erzeugt und komponiert
werden koennen. Das behauptet das Tutorial aber nicht mehr weiter wegen
einem komischen Racecondition das sie sich im Textfeld nicht erklären
konnten.

Das klingt nach "wir wissen nicht wieso, aber macht einfach alles in einem
Thread. Das ist zwar furchtbar langsam um umstaendlich aber unsere Library
kommt mit sonst nichts zurrecht"


Gruss
Bernd

Bernd Eckenfels

unread,
Feb 5, 2006, 8:25:17 PM2/5/06
to
Michael Rauscher <mich...@gmx.de> wrote:
> Was soll man davon halten?

Ich würd mich schämen so was in ein so weit verbreitetes Tutorial zu
schreiben.

Gruss
Bernd

Torsten Kunkel

unread,
Feb 5, 2006, 9:03:25 PM2/5/06
to
Michael Hüttermann <mic...@huettermann.net> wrote:
> wenn du dich zur zeit im EDT befindest musst du es nicht machen.

Ich bin ja aber nie im EDT weil das ja ein interner Swingthread ist.
Innerhalb der Event-Verarbeitung zu sein reicht scheinbar ja nicht,
denn ich mache ja keine eigenen neuen Threads auf, ich habe beim
Knopfdruck einen Actionlistener der ruft dann eine Methode auf, der
dann über mehrere Ecken (alles normale Methodenaufrufe) das
setVisible(true) und setVisible(false) ausführt.
Ich verlasse hier den eigentlichen Thread nie.

Ich habe also nun etwas umgebaut:
public void showWaitDialog() {


Runnable show = new Runnable() {
public void run() {

waitingDialog.display();
}
};
SwingUtilities.invokeLater(show);
}

public void hideWaitDialog() {


Runnable show = new Runnable() {
public void run() {

waitingDialog.setVisible(false);
}
};
SwingUtilities.invokeLater(show);
}


Aber: Pustekuchen
Ich habe exakt dieselben Probleme weiterhin, dabei sollte doch der
Aufruf nun genau dem entsprechen was im Tutorial steht.

Mal abgesehen davon, dass es bei mir nicht geht, verstehe ich einfach
nicht so wirklich was das ganze soll. So wie ich es verstanden habe
müßte ich das bei JEDER stelle einbauen wo ich irgendwas auf der GUI
ändere. Will ich beim Knopfdruck einen Wert hochzählen muß ich es
haben, will ich beim Knopfdruck eine Maske füllen muß ich es haben
etc. Jedesmal wenn ich einen Wert oder eine Eigenschaft in der GUI
ändere muß ich soetwas einbauen. Ich finde das irgendwie derbe
umständlich.

Frustrierte Grüße

Torsten

Bernd Eckenfels

unread,
Feb 5, 2006, 9:30:20 PM2/5/06
to
Torsten Kunkel <ne...@tkunkel.de> wrote:
> Ich bin ja aber nie im EDT weil das ja ein interner Swingthread ist.

Alle action callbacks (Events) werden durch den EDT aufgerufen. Deswegen
solltest du in denen auch nie langlaufende Aktionen machen. In deinem
Beispiel haste halt noch keine...

Gruss
Bernd

Torsten Kunkel

unread,
Feb 5, 2006, 9:43:05 PM2/5/06
to
Hi,
habe mal ein vollständiges Beispiel mit dem Problem zusammengebaut:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class SchnellerDialog extends JFrame implements ActionListener {

JButton dummy;

JFrame frame;

public SchnellerDialog() {
frame = new JFrame();
dummy = new JButton("Dummy");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(dummy);
this.pack();
this.setVisible(true);
dummy.addActionListener(this);
}

public static void main(String[] args) {

new SchnellerDialog();
}

public void actionPerformed(ActionEvent e) {
if (e.getSource() == dummy) {
frame.setVisible(true);
frame.setVisible(false);
}
}
}


Baue ich das um:

public void actionPerformed(ActionEvent e) {
if (e.getSource() == dummy) {
Runnable doWorkRunnable = new Runnable() {
public void run() {
frame.setVisible(true);
frame.setVisible(false);
}
};
SwingUtilities.invokeLater(doWorkRunnable);
}
}

Dann bringt das genau nix :/

Torsten Kunkel

unread,
Feb 5, 2006, 9:49:25 PM2/5/06
to
Hi Bernd,

>> Ich bin ja aber nie im EDT weil das ja ein interner Swingthread ist.
> Alle action callbacks (Events) werden durch den EDT aufgerufen. Deswegen
> solltest du in denen auch nie langlaufende Aktionen machen. In deinem
> Beispiel haste halt noch keine...

Soweit so gut. Ich sehe es vollkommen ein, dass lange Aktionen die GUI
sperren würden, oder besser gesagt nicht nur die GUI halt alle
Operationen außer dem einen laufenden Thread.
Abbbbba :) Selbst bei den ganz kurzen Aktionen gehts bei mir ja nicht,
und das ist eine Sache die mich gerade extrem ärgert :)
Ich mein komplizierte Datenbankabfragen, GUI-Design und all der andere
Quatsch geht prima, aber dann taucht so ein Problem hier auf.
Eigentlich sollte sowas doch Pippifax sein :/

Danke auf alle Fälle schonmal :)

Bernd Eckenfels

unread,
Feb 5, 2006, 10:06:58 PM2/5/06
to
Torsten Kunkel <ne...@tkunkel.de> wrote:
> frame = new JFrame();
> dummy = new JButton("Dummy");
> this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
> this.add(dummy);
> this.pack();
> this.setVisible(true);
> dummy.addActionListener(this);

Obiges muss im EDT laufen nicht das:

> public void actionPerformed(ActionEvent e) {
> if (e.getSource() == dummy) {
> frame.setVisible(true);
> frame.setVisible(false);
> }
> }
> }

denn das laeuft schon im EDT.

Gruss
Bernd

Torsten Kunkel

unread,
Feb 5, 2006, 10:18:46 PM2/5/06
to
Bernd Eckenfels <be-n...@lina.inka.de> wrote:
> Torsten Kunkel <ne...@tkunkel.de> wrote:
>> frame = new JFrame();
>> dummy = new JButton("Dummy");
>> this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
>> this.add(dummy);
>> this.pack();
>> this.setVisible(true);
>> dummy.addActionListener(this);
>
> Obiges muss im EDT laufen nicht das:

SchnellerDialog me;

public SchnellerDialog() {
me = this;


Runnable doWorkRunnable = new Runnable() {
public void run() {

frame = new JFrame();
dummy = new JButton("Dummy");

me.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
me.add(dummy);
me.pack();
me.setVisible(true);
dummy.addActionListener(me);
}
};
SwingUtilities.invokeLater(doWorkRunnable);
}


Geht aber genausowenig, leider.



>> public void actionPerformed(ActionEvent e) {
>> if (e.getSource() == dummy) {
>> frame.setVisible(true);
>> frame.setVisible(false);
>> }
>> }
>> }
>
> denn das laeuft schon im EDT.

Aber laut dem Tutorial wird doch alles aus dem EDT "korrekt"
abgearbeitet, doch genau das ist hier nicht der Fall. Der das
setVisible(false) wird nicht "korrekt" verarbeitet, die Zeile wird
ausgeführt, aber der Effekt des Ausblendens tritt nicht ein. Baue ich
einen sleep(100) dazwischen, gehts perfekt.

Gruß

Brettvormkopftorsten

Bernd Eckenfels

unread,
Feb 5, 2006, 10:54:49 PM2/5/06
to
Torsten Kunkel <ne...@tkunkel.de> wrote:
>>> frame.setVisible(true);
>>> frame.setVisible(false);
>> denn das laeuft schon im EDT.
>
> Aber laut dem Tutorial wird doch alles aus dem EDT "korrekt"
> abgearbeitet, doch genau das ist hier nicht der Fall. Der das
> setVisible(false) wird nicht "korrekt" verarbeitet, die Zeile wird
> ausgeführt, aber der Effekt des Ausblendens tritt nicht ein. Baue ich
> einen sleep(100) dazwischen, gehts perfekt.

Du musst dem EDT Zeit geben einmal nach jedem Befehl durchzulaufen. Also
z.b. einen eigenen Thread machen der invokeAndWait macht auf jeweils einem
Codeblock der nur einen der Befehle enthaelt.


Gruss
Bernd

Wanja Gayk

unread,
Feb 6, 2006, 2:54:44 AM2/6/06
to
ne...@tkunkel.de said...

> frame.setVisible(true);
> frame.setVisible(false);
^^^^^^
Kein Wunder, dass da nix passiert, würde ich sagen..

Andrey Kuznetsov

unread,
Feb 6, 2006, 3:39:59 AM2/6/06
to
>> Was soll man davon halten?
>
> Ich würd mich schämen so was in ein so weit verbreitetes Tutorial zu
> schreiben.

Das ist nur ehrlich.
Oder sollten die über dieses Problem einfach schweigen?
Es ist leider so, dass SUN meistens Jahre braucht um ein bug zu beseitigen.
Zumindest hier ist man gewarnt.

--
Andrey Kuznetsov
http://uio.imagero.com Unified I/O for Java
http://reader.imagero.com Java image reader
http://jgui.imagero.com Java GUI components and utilities


Michael Hüttermann

unread,
Feb 6, 2006, 5:18:36 AM2/6/06
to

Torsten Kunkel schrieb:

Wenn Dir irgendwas zuviel ist dann führe ein intermediate layer ein,
eine indirektion die genau das wegkapselt. BTW: ob du gerade im EDT
bist kannst du rauskriegen über isEventDispatchThread() von
SwingUtilities.

Michael

Wanja Gayk

unread,
Feb 6, 2006, 5:48:04 AM2/6/06
to
ne...@tkunkel.de said...

> > wenn du dich zur zeit im EDT befindest musst du es nicht machen.
>
> Ich bin ja aber nie im EDT weil das ja ein interner Swingthread ist.

Und was sagt:
SwingUtilities.isEventDispatchThread()
dazu?

Karsten Lentzsch

unread,
Feb 6, 2006, 6:52:31 AM2/6/06
to
Michael Rauscher schrieb:

> Bezogen habe ich mich auf folgenden Absatz:
>
> Note: We used to say that you could create the GUI on the main thread as

> long as you didn't modify components that had already been realized. [...]


>
> Mit meiner Vermutung mag ich daneben liegen (daher "Vermutung"). Ich
> weiß aber nicht, wie Du darauf kommst, ich würde annehmen, Kathy Walrath
> (oder wer auch immer) hätte Swing und/oder Threads nicht verstanden.

Ich hab' gar nichts angenommen, nur gesagt,
dass Kathy die Situation verstanden hat.

> Tatsache ist, dass ein Fehler dahintersteckt. [...]

Nein. Dahinter steckt 1) eine Design-Entscheidung für Swing,
und 2) eine Entscheidung für's Tutorial. Aus gutem Grund
nutzt und braucht Swing die Single-Thread-Regel; ein
multi-threaded Toolkit ist manchmal einfacher zu benutzen,
aber viel schwerer zu erweitern. Jeder Anbieter einer JComponent
müsste sich dann an die multi-thread-Programmierregeln halten.

Im Tutorial kann man die allgemeinere Aussage stehen lassen,
wann man Swing-Komponenten aus anderen Thread ändern darf.
Oder man weist einen einfachen Weg, Probleme ganz zu meiden.
In den neueren Versionen des Tutorials wird Letzteres getan.

Der Hintergrund ist eigentlich nicht so schwer zu verstehen.
Grob gesagt: man kann mit Swing-Komponenten aus allen Threads
irgendwas machen, solange man die Komponenten nicht in der
GUI "benutzt", sie keine Events des EDT behandeln, auch
keine Zeichenevents. Solgange die Komponenten nicht realisiert
sind, sind sie wie irgendein anderen Objektgraph, auf dem
man operieren kann. Anders wird's, wenn die Komponenten
gezeichnet werden und am Event-Dispatch teilnehmen.

Ich baue Swing-Oberflächen nicht im EDT, unter anderem,
um den Aufbaufortschritt anzuzeigen. Dann muss ich aber
darauf achten, die realisierten Komponenten nicht zu
modifizieren.

Irgendwo hat das Swing-Team begründet, warum Swing
nicht multi-threaded gebaut worden ist. Ich glaube
das ist in der Artikelserie "Threads and Swing";
und ich glaube, Graham Hamilton hat neulich nochmal
erläutert, warum man auch für Java 7 dabei bleiben will.

-Karsten

Karsten Lentzsch

unread,
Feb 6, 2006, 6:57:39 AM2/6/06
to
Bernd Eckenfels schrieb:

> Wir beziehen uns auf die Aussage, dass man nicht-realisierte Swing Objekte
> eigentlich auch in einem anderen Thread (z.b. main) erzeugt und komponiert
> werden koennen. Das behauptet das Tutorial aber nicht mehr weiter wegen
> einem komischen Racecondition das sie sich im Textfeld nicht erklären
> konnten.

Man kann Swing-Komponenten auch in einem anderen Thread erzeugen
und zusammen bauen; nicht nur "eigentlich".

> Das klingt nach "wir wissen nicht wieso, aber macht einfach alles in einem
> Thread. Das ist zwar furchtbar langsam um umstaendlich aber unsere Library
> kommt mit sonst nichts zurrecht"

Die Aussage im Tutorial klingt für mich anders.

Wenn jemand nicht genau weiß, ob er realisierte Komponenten
aus einem nicht EDT-Thread modifiziert, dann würde ich ihm
empfehlen, eben im EDT zu bauen. Das ist einfach, nicht immer
der beste Weg, aber eben einfach.

-Karsten

Bernd Eckenfels

unread,
Feb 6, 2006, 7:01:48 AM2/6/06
to
Karsten Lentzsch <kar...@jgoodies.com> wrote:
>> Note: We used to say that you could create the GUI on the main thread as
>> long as you didn't modify components that had already been realized. [...]

> Der Hintergrund ist eigentlich nicht so schwer zu verstehen.


> Grob gesagt: man kann mit Swing-Komponenten aus allen Threads
> irgendwas machen, solange man die Komponenten nicht in der
> GUI "benutzt", sie keine Events des EDT behandeln, auch
> keine Zeichenevents. Solgange die Komponenten nicht realisiert
> sind, sind sie wie irgendein anderen Objektgraph, auf dem
> man operieren kann. Anders wird's, wenn die Komponenten
> gezeichnet werden und am Event-Dispatch teilnehmen.

Genau das steht im Tutorial, und dann steht drin dass es bei ihrem TextArea
im Main Thread nicht geklappt hat und weil sie nicht wissen wieso haben sie
auch das realisieren der Komponenten in den EDT gepackt (was uebrigens die
sache sehr verlangsamt)

Gruss
Bernd

Bernd Eckenfels

unread,
Feb 6, 2006, 7:02:58 AM2/6/06
to
Karsten Lentzsch <kar...@jgoodies.com> wrote:
> Man kann Swing-Komponenten auch in einem anderen Thread erzeugen
> und zusammen bauen; nicht nur "eigentlich".

Wie liest keiner den Text auf den wir uns beziehen?

> Die Aussage im Tutorial klingt für mich anders.

Da steht drin sie wissen nicht wieso es Probleme macht.

Gruss
Bernd

Karsten Lentzsch

unread,
Feb 6, 2006, 7:07:30 AM2/6/06
to
Wanja Gayk schrieb:

>[...]


> Ich habe dazu eine recht passable Hilfsklasse, die "JobQueue" gebaut
> (Quelltext folgt).

> [...]

Wo siehst Du Vor- und Nachteile der JobQueue
gegenüber den alten und neuen SwingWorkern?

Soweit ich sehe, kann der SwingWorker auch noch:
1) im finished-Teil auf das Ergebnis der
Hintergrundberechnung zugreifen.
2) Er synchonisiert Zugriffe auf das Rechenergebnis
in #get.

Der neue Swing-Worker aus Java 6 kann noch:
3) Zwischenergebnisse melden - im EDT.

-Karsten

Karsten Lentzsch

unread,
Feb 6, 2006, 7:15:35 AM2/6/06
to
Bernd Eckenfels schrieb:

> Genau das steht im Tutorial, und dann steht drin dass es bei ihrem TextArea
> im Main Thread nicht geklappt hat und weil sie nicht wissen wieso haben sie
> auch das realisieren der Komponenten in den EDT gepackt (was uebrigens die
> sache sehr verlangsamt)

Da steht, dass es in einem Beispiel nicht geklappt hat,
nicht, dass es mit einer allgemeinen JTextArea nicht klappt.

Im EDT kann genauso schnell gearbeitet werden,
wie in anderen Threads; er ist nicht ererbt langsamer.
Mich wundert, dass Du beobachtest, dass der EDT-Bau
*sehr* verlangsamt. Hast Du das mal untersucht?

-Karsten

Michael Rauscher

unread,
Feb 6, 2006, 8:06:11 AM2/6/06
to
Hallo Karsten,

Karsten Lentzsch schrieb:
> Michael Rauscher schrieb:
>

>> Tatsache ist, dass ein Fehler dahintersteckt. [...]
>
>
> Nein. Dahinter steckt 1) eine Design-Entscheidung für Swing,
> und 2) eine Entscheidung für's Tutorial.

Im Tutorial wird doch klar ein Fehler eingeräumt: "We used to say..."
und weiter "While this worked for most applications, in certain
situations it could cause problems.".

> Der Hintergrund ist eigentlich nicht so schwer zu verstehen.
> Grob gesagt: man kann mit Swing-Komponenten aus allen Threads
> irgendwas machen, solange man die Komponenten nicht in der
> GUI "benutzt", sie keine Events des EDT behandeln, auch
> keine Zeichenevents.

Klar.

> Solgange die Komponenten nicht realisiert
> sind, sind sie wie irgendein anderen Objektgraph, auf dem
> man operieren kann.

NACK. Wenn dem so wäre, dann hätte man das ursprüngliche Statement ja
nicht korrigieren müssen.

Zusätzlich habe ich im Report zu Bug 5042754 noch folgende Erklärung
gefunden:

While we have previously claimed that it is safe to create and modify a
GUI on the main thread until it is realized, that is only mostly true.
It turns out that there are some Swing methods that start up the event
dispatch thread before the GUI is realized and this results in two
threads accessing the GUI at the same time. This is very prone to
deadlocks, and Swing has always claimed not to be thread safe.

Dieser Erklärung entnehme ich, dass "es sich herausgestellt hat" (*),
dass es "einige Swing-Methoden" (**) gibt, die den EDT starten, bevor
die GUI realisiert wurde. Damit stimmt natürlich die ursrpüngliche
Aussage nicht mehr, die GUI könnte im main-Thread erzeugt und
modifiziert werden, so lange sie nicht realisiert ist.

Wenn ich das richtig verstanden habe und dem so ist, dann hat das für
mich nichts mit Entscheidungen fürs Tutorial zu tun und ein "mostly
true" macht die Sache auch nicht besser. Die Aussage wäre dann
schlichtweg falsch, sprich ein Fehler.

Nicht auszuschließen ist, dass ich das alles einfach völlig falsch sehe.

Gruß
Michael

* solche Aussagen treffe ich eigentlich nur dann, wenn es sich um
Dinge handelt, die nicht in meiner unmittelbaren Verantwortung
liegen. Hab ich da was verpasst?

** geht's vielleicht auch "etwas" genauer? Weißt Du (oder sonst jemand
da draußen), welche genau das sind?

Torsten Kunkel

unread,
Feb 6, 2006, 4:39:15 AM2/6/06
to
Wanja Gayk <brixo...@yahoo.com> wrote:
>> frame.setVisible(true);
>> frame.setVisible(false);
> ^^^^^^
> Kein Wunder, dass da nix passiert, würde ich sagen..
>

Wieso? Erst einblenden dann ausblenden und der Frame steht dann noch
auf dem Monitor. Wieso ist das kein Wunder?

Michael Rauscher

unread,
Feb 6, 2006, 8:44:51 AM2/6/06
to
Torsten Kunkel schrieb:

Wirklich? Du hast dann zwei Frames auf dem Monitor?

Gruß
Michael

Torsten Kunkel

unread,
Feb 6, 2006, 9:51:57 AM2/6/06
to
Hi Wanja,

Wanja Gayk <brixo...@yahoo.com> wrote:
> ne...@tkunkel.de said...
>
>> > wenn du dich zur zeit im EDT befindest musst du es nicht machen.
>>
>> Ich bin ja aber nie im EDT weil das ja ein interner Swingthread ist.
>
> Und was sagt:
> SwingUtilities.isEventDispatchThread()
> dazu?

Nun wirds lustig :)


public void actionPerformed(ActionEvent e) {
if (e.getSource() == dummy) {

System.out.println(SwingUtilities.isEventDispatchThread());
frame.setVisible(true);
frame.setVisible(false);
}
}

ich habe hinterher weiterhin meinen nicht-ausgeblendeten frame und
gleichzeitig eine "true" aussage, ich befinde mich also im EDT, alle
befehle müßten also korrekt verarbeitet werden, aber dennoch bleibt
das Fenster stehen.

So langsam glaube ich das Problem ist ein Bug im JDK....

Gruß

Torsten

Torsten Kunkel

unread,
Feb 6, 2006, 9:47:11 AM2/6/06
to
Michael Rauscher <mich...@gmx.de> wrote:
>> Wieso? Erst einblenden dann ausblenden und der Frame steht dann noch
>> auf dem Monitor. Wieso ist das kein Wunder?
>
> Wirklich? Du hast dann zwei Frames auf dem Monitor?

Ja, den mit dem Button und den der eingeblendet wurde und eigentlich
ausgeblendet werden sollte.
Probier es einfach mal aus, ein Beispiel habe ich angehängt.

Torsten Kunkel

unread,
Feb 6, 2006, 9:54:11 AM2/6/06
to
Hi Michael,

> Wenn Dir irgendwas zuviel ist dann führe ein intermediate layer ein,
> eine indirektion die genau das wegkapselt. BTW: ob du gerade im EDT
> bist kannst du rauskriegen über isEventDispatchThread() von
> SwingUtilities.

Habs gerade Wanja geantwortet, ich BIN im EDT wie ich eben feststellte
und daher nun an einem Punkt angekommen wo ich überhaupt gar nichtmehr
durchsteige *grinst schief* Denn wen nich im EDT bin heißt das ja ich
müßte alles richtig gemacht haben, aber

public void actionPerformed(ActionEvent e) {
if (e.getSource() == dummy) {
System.out.println(SwingUtilities.isEventDispatchThread());
frame.setVisible(true);
frame.setVisible(false);
}
}

liefert zwar true, aber dennoch bleibt der frame sichtbar.

Gruß

Torsten

Karsten Lentzsch

unread,
Feb 6, 2006, 10:41:08 AM2/6/06
to
Michael Rauscher schrieb:

> [...]

> Im Tutorial wird doch klar ein Fehler eingeräumt: "We used to say..."
> und weiter "While this worked for most applications, in certain
> situations it could cause problems.".

Das räumt für mich keinen Fehler ein, sondern zeigt nur,
dass das Tutorial nun Dinge anders sagt als vorher.
Ich hab daraus nicht gelesen, was das "problem" war,
eine falsche Regelbeschreibung, ein Verständnisproblem,
oder eine falsche Anwendung der Regel in einer Demo.
Der von Dir genannte Bug klärt aber über die Art des Problem
auf - etwas, was ich im Tutorial-Text nicht fand.

Mal ein Beispiel von mir zu den JGoodies Forms:
"In the Forms tutorial I used to say that users
should favor the DefaultPanelBuilder over the PanelBuilder.
While this works for most applications, in certain situations
is could cause problems. These problems are that layout readers
frequently get confused about the implicit operations
performed by the DefaultFormBuilder. I now recommend to do xy."
Ich habe also früher A gesagt, und nun B, um ein
Verständnisproblem zu meiden, keinen Fehler.

Wie auch immer. Die Analyse zu Bug 5042754 zeigt,
dass die alte Beschreibung der Single-Thread-Regel
nicht (im Allgemeinen) gilt. Sie ist zu erweitern
von "realized" auf das allgemeinere: "die Swing-Komponente
wird nicht vom EDT benutzt." Das Letztere ist aber schwierig
zu sehen und zu verstehen.

> Wenn ich das richtig verstanden habe und dem so ist, dann hat das für
> mich nichts mit Entscheidungen fürs Tutorial zu tun und ein "mostly
> true" macht die Sache auch nicht besser. Die Aussage wäre dann
> schlichtweg falsch, sprich ein Fehler.

Die alte Aussage war falsch, einen Fehler in Swing sehe ich nicht.

> [...]

> ** geht's vielleicht auch "etwas" genauer? Weißt Du (oder sonst jemand
> da draußen), welche genau das sind?

Soweit ich sehe, kommen Methoden rund um Textkomponenten in Frage.
Ich hätte nach der Bug-Beschreibung auch #validate und #revalidate
in Verdacht, ähnliche Probleme auszulösen. Es wundert mich,
dass der Bug-Reporter keinen Deadlock produzieren konnte
mit seiner Variante, die invalidate/validate aufruft.
Eine weitere besondere Ecke ist JEditorPane#setText, #setPage.

-Karsten

Wanja Gayk

unread,
Feb 6, 2006, 12:04:39 PM2/6/06
to
kar...@jgoodies.com said...

> Wanja Gayk schrieb:
>
> >[...]
> > Ich habe dazu eine recht passable Hilfsklasse, die "JobQueue" gebaut
> > (Quelltext folgt).
> > [...]
>
> Wo siehst Du Vor- und Nachteile der JobQueue
> gegenüber den alten und neuen SwingWorkern?

Ich habe nie von einem "Vorteil" gesprochen, ich hab's mir irgendwann
mal gebaut und benutze es halt seit dem und es funktioniert für meine
Zwecke gut genug.

Bernd Eckenfels

unread,
Feb 6, 2006, 1:04:39 PM2/6/06
to
Torsten Kunkel <ne...@tkunkel.de> wrote:
> frame.setVisible(true);
> frame.setVisible(false);

Erst am Ende des EDT wird die (letzte) Änderung gezeichnet, was also
erwartest du zu sehe? (Antwort: nichts)

Gruss
Bernd

Karsten Lentzsch

unread,
Feb 6, 2006, 1:43:59 PM2/6/06
to
Wanja Gayk schrieb:

> Ich habe nie von einem "Vorteil" gesprochen, ich hab's mir irgendwann
> mal gebaut und benutze es halt seit dem und es funktioniert für meine
> Zwecke gut genug.

Du hast nicht davon gesprochen, ich aber danach gefragt.
Ich möchte verstehen, ob der SwingWorker die JobQueue
umfasst. Wenn ja, dann brauche ich mir die JobQueue
nicht merken. Ansonsten würde ich sie einordnen wollen
zwischen Spin, Foxtrott, altem und neuen SwingWorker.

Umfasst der SwingWorker die JobQueue-Fähigkeiten?

Gruß,
Karsten

Michael Rauscher

unread,
Feb 6, 2006, 2:51:58 PM2/6/06
to
Karsten Lentzsch schrieb:

> Michael Rauscher schrieb:
>
>> [...] Im Tutorial wird doch klar ein Fehler eingeräumt: "We used to
>> say..." und weiter "While this worked for most applications, in
>> certain situations it could cause problems.".
>
>
> Das räumt für mich keinen Fehler ein, sondern zeigt nur,
> dass das Tutorial nun Dinge anders sagt als vorher.

Naja, ist natürlich vom Kontext abhängig. Offensichtlich besteht hier
Interpretationsspielraum.

> Ich hab daraus nicht gelesen, was das "problem" war,
> eine falsche Regelbeschreibung, ein Verständnisproblem,
> oder eine falsche Anwendung der Regel in einer Demo.

Richtig. Es liest sich, als wüsste man selbst nicht, was das Problem nun
eigentlich ist.

> Der von Dir genannte Bug klärt aber über die Art des Problem
> auf - etwas, was ich im Tutorial-Text nicht fand.

Leider. Anstatt klar den Grund reinzuschreiben, wird über tausend Ecken
um das Problem herum geschrieben. Dadurch wird o. g. Eindruck nur noch
verstärkt.

>
> Mal ein Beispiel von mir zu den JGoodies Forms:
> "In the Forms tutorial I used to say that users
> should favor the DefaultPanelBuilder over the PanelBuilder.
> While this works for most applications, in certain situations
> is could cause problems. These problems are that layout readers
> frequently get confused about the implicit operations
> performed by the DefaultFormBuilder. I now recommend to do xy."
> Ich habe also früher A gesagt, und nun B, um ein
> Verständnisproblem zu meiden, keinen Fehler.

Das ist IMO nicht ganz das selbe, da es sich hier lediglich um eine
Empfehlung, nicht aber um eine Feststellung handelt.

>
> Die alte Aussage war falsch, einen Fehler in Swing sehe ich nicht.

Darum habe ich in meinem vorletzten Posting offen gelassen, ob der
Fehler in Swing, im Tutorial oder auch nur in dem angesprochenen Demo
liegt. Irgendwo war auf jeden Fall einer :)

Und jetzt nochmal zurück zu meiner ursprünglich ausgeführten Vermutung,
um die es Dir ja eigentlich ging:

Ich stelle zunächst fest, dass eine Regel (die ursprüngliche Aussage im
Tutorial) aufgestellt wurde. Dann gibt es IMO zwei Möglichkeiten.
Entweder war die Regel falsch oder wurde die Regel an einer Stelle (es
ist ja nur von text area die Rede) in Swing nicht beachtet. Da es sonst
überall zu funktionieren scheint, war natürlich letzteres naheliegend
und ich hatte die Vermutung, dass ein Swing Bug dahintersteckt, den man
einfach per Workaround ausmerzt.

Ob es nun so war oder nicht, vermag ich immer noch nicht zu beurteilen.
Ich verspüre aber auch nicht das Bedürfnis, mich diesbezüglich weiter zu
engagieren, da ich ja weiß, wie ich mit dem Problem umzugehen habe :)

>
>> [...] ** geht's vielleicht auch "etwas" genauer? Weißt Du (oder sonst
>> jemand
>> da draußen), welche genau das sind?
>
>
> Soweit ich sehe, kommen Methoden rund um Textkomponenten in Frage.
> Ich hätte nach der Bug-Beschreibung auch #validate und #revalidate
> in Verdacht, ähnliche Probleme auszulösen. Es wundert mich,
> dass der Bug-Reporter keinen Deadlock produzieren konnte
> mit seiner Variante, die invalidate/validate aufruft.
> Eine weitere besondere Ecke ist JEditorPane#setText, #setPage.

Danke. Vielmehr wundert mich, dass es keine Aufstellung darüber gibt.


Gruß
Michael

Michael Hüttermann

unread,
Feb 6, 2006, 3:12:58 PM2/6/06
to

Torsten Kunkel schrieb:

gleich hast du mich soweit dass ich deinen code mal selber laufen
lasse. also dass was du da machst kann niemals richtig sein. diese
kombination aus setVisible true setVisible false sollte dich auch etwas
stutzig machen..

Michael

Jochen Theodorou

unread,
Feb 6, 2006, 3:33:08 PM2/6/06
to
Michael Hüttermann schrieb:
[...]

> diese
> kombination aus setVisible true setVisible false sollte dich auch etwas
> stutzig machen..

du meinst sowas darf nicht gehen? Wenn du Thread verfolgt hast weisst du
ja dass das nciht das ursprüngliche Problem ist

Gruss theo

Torsten Kunkel

unread,
Feb 6, 2006, 3:28:03 PM2/6/06
to
Hey Berd,

Absolut korrekt :) Ich erwarte nichts(!!!) zu sehen.
Aber was sehe ich? Den Frame...

Ich bin mir aber inzwischen sicher, dass es ein Sun-Bug ist.
1.5.0_02 und _06 unter Linux bringen den Frame sichtbar.
1.4.2 unter Linux und 1.4.2 und 1.5.0_05 unter Windows zeigen "nichts"
also das was man erwartet.
Derselbe Code wird also auf verschiedenen Plattformen unterschiedlich
ausgeführt, und das muß ein Bug sein.

So wie du es beschreibst und so wie es sich unter Windows verhält sehe
ich es als logisch an, aber genau das verhalten tritt bei mir ja nicht
auf, daher meine Verwirrung.

Gruß

Torsten

Michael Hüttermann

unread,
Feb 6, 2006, 3:51:16 PM2/6/06
to

Jochen Theodorou schrieb:

ich habe nicht behaupten dass es nicht gehen würde. ja, ich habe den
gesamten thread verfolgt.

Michael

Torsten Kunkel

unread,
Feb 6, 2006, 3:58:03 PM2/6/06
to
Jochen Theodorou <blac...@uni.de> wrote:
> Michael Hüttermann schrieb:
> [...]
>> diese
>> kombination aus setVisible true setVisible false sollte dich auch etwas
>> stutzig machen..

Das ist im Beispiel so, schau mal öhm, irgendwo oben ;) dazwischen
fand im original eine Berechnung statt, die wenn sie extrem wenig
zutun hat halt sehr wenig Zeit verbrät, im Extremfall quasi null, also
habe ich sie hier für das Beispiel wie in einem super-extrem-fall
komplett weggelassen.
Das es so wie es da steht keinen Sinn macht ist mir klar, aber es ist
ja auch nur eine Visualisierung des Problemes
Das ändert ja aber nichts daran, dass es technisch ok sein müßte.

> du meinst sowas darf nicht gehen? Wenn du Thread verfolgt hast weisst du
> ja dass das nciht das ursprüngliche Problem ist

Doch, genau das ist das Problem. Der setVisible(false) wird nämlich
bei mir nicht ausgeführt.

Michael Hüttermann

unread,
Feb 6, 2006, 4:04:55 PM2/6/06
to

Torsten Kunkel schrieb:

ja ist mir alles klar. das hab ich dir aber auch in dem thread
geschrieben den du eigens dafür aufgemacht hast.

Michael

Michael Hüttermann

unread,
Feb 6, 2006, 4:06:00 PM2/6/06
to

Michael Hüttermann schrieb:

ich seh gerad das warst nicht du das war ein anderer.

Michael

Torsten Kunkel

unread,
Feb 6, 2006, 4:30:13 PM2/6/06
to
Hi Michael,

> ich seh gerad das warst nicht du das war ein anderer.

danke für den Hinweis, dann sinds ja schonmal 2 Leute die beide das
Problem haben, beide unter Linux, beide mit der 1.5.0.
Langsam ists für mich kein Zufall mehr.

Michael Hüttermann

unread,
Feb 6, 2006, 4:44:00 PM2/6/06
to

Torsten Kunkel schrieb:

es sind sogar noch mehr als 2....

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5109571

Michael

Michael Rauscher

unread,
Feb 6, 2006, 5:08:08 PM2/6/06
to
Torsten Kunkel schrieb:

Wenn ich das ausprobiere, bleibt nur der Frame mit dem Button übrig.

Gruß
Michael

Wanja Gayk

unread,
Feb 6, 2006, 5:49:25 PM2/6/06
to
kar...@jgoodies.com said...

Ich habe mir den SwingWorker gerade mal angeschaut, nein, er macht etwas
anderes.

So wie ich das sehe, führt der SwingWorker nur eine einzelne Arbeit
außerhalb des EDT aus (die construct()-methode), bietet in ihr einen
return-Wert und die Möglichkeit nach Abarbeitung der construct()-Methode
in der finished()-Methode etwas im EDT auszuführen. Richtig?

Die JobQueue ist anders.
Die JobQueue ist nichts anderes, als eine Klasse, die Runnables
außerhalb des EDT in FIFO-Reihenfolge ausführt, aber nicht nur ein
einzelnes, sondern du kannst ihr davon so viele davon geben, wie du
magst. Du kannst mehrere lange Jobs, in schneller Reihenfolge in die
Queue pumpen, die Queue arbeitet sie dann schön der Reihe nach ab, und
das, während du du neue hinein jagst.

Ich habe mir das Ding derzeit gebaut, um einem Problem beizukommen:

Das war der alte Code (vereinfacht):

public void actionPerformed(final ActionEvent e){
new Thread("bla"){
public void run(){
final Object result = doSomething() //.. that takes 1-5 seconds
SwingUtilities.invokeLater(new Runnable(){
public void run(){
updateGUIWithSomethingBasedOn(result);
}
});
}
}.start();
}

Die Action startete also immer einen neuen Thread, der dauerte, sagen
wir mal 3 Sekunden und danach schieb er sein Ergebnis per invokeLater in
eine Tabelle.
Während der arbeitete löste man die Action möglicherweise erneut aus,
der davon ausgelöste, neue Thread dauerte jetzt z.B. nur eine enzige
Sekunde und schrieb dann seine Ergebnisse in die Tabelle.
Da es um Datenbank-Abfragen ging, waren die Ergebnisse nicht identisch
und so hatte der alte Thread also die Ergebnisse vom, später
gestarteten, zweiten Thread wieder rückgängig gemacht, einfach, weil der
alte länger brauchte.
Eigentlich war es damals sogar noch schlimmer, die komplette Tabelle war
versaut. :-)

Ich hab mir daraufhin diese "JobQueue" Klasse gebaut und, statt in der
Action immer einen neuen Thread zu starten, einfach Runnables in eine
für diese Action zuständige JobQueue geschickt:

private final JobQueue QUEUE = new JobQueue("BlaQueue");

public void actionPerformed(final ActionEvent e){
QUEUE.enqueue(new Runnable(){
public void run(){
final Object result = doSomething() //.. that takes 1-5 seconds
SwingUtilities.invokeLater(new Runnable(){
public void run(){
updateGUIWithSomethingBasedOn(result);
}
});
}
});
}

Damit war garantiert, dass, egal wie oft und mit welcher Geschwindigkeit
ich das Event auslöse und egal wie lange der einzelne Job dauerte, alles
immer fein hintereinander ausgeführt wurde, und der EDT trotzdem nicht
geblockt war. Das Letzte Ergebnis war also auch immer dasd Ergebnis, was
zuletzt angefordert wurde.

Mit dem SwingWorker geht das, soweit ich das sehe, nicht.
Er erfüllt also IMO eine andere Aufgabe.

Bernd Eckenfels

unread,
Feb 6, 2006, 6:22:33 PM2/6/06
to
Torsten Kunkel <ne...@tkunkel.de> wrote:
> Das ist im Beispiel so, schau mal öhm, irgendwo oben ;) dazwischen
> fand im original eine Berechnung statt, die wenn sie extrem wenig
> zutun hat halt sehr wenig Zeit verbrät, im Extremfall quasi null, also
> habe ich sie hier für das Beispiel wie in einem super-extrem-fall
> komplett weggelassen.

Wie gesagt, es kommt nicht auf die Zeit an, sondern du musst dazwischen den
EDT einmal verlassen.

Gruss
Bernd

Torsten Kunkel

unread,
Feb 6, 2006, 4:50:19 PM2/6/06
to

*brummelt gespielt*
Wollte morgen auch mal suchen aber eigentlich erstmal ins Bett und
morgen in ruhe schauen, das brauche ich ja nun nimma.
Danke dir :)

Torsten Kunkel

unread,
Feb 6, 2006, 4:51:25 PM2/6/06
to
Wie Michael rausgesucht hatte ist das Verhalten ein Javabug:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5109571

Danke für eure Hilfe.

Torsten Kunkel

unread,
Feb 6, 2006, 6:28:44 PM2/6/06
to

Du nutzt als Newsclient Mozilla unter Windows , daher gehe ich einfach
einmal davon aus, dass du auch unter Windows versucht hast das
nachzuvollziehen. Es ist "leider" nur unter Linux nachvollziehbar wie
inzwischen klar wurde.
Aber danke fürs testen :)

Michael Rauscher

unread,
Feb 6, 2006, 6:35:46 PM2/6/06
to
Torsten Kunkel schrieb:

> Du nutzt als Newsclient Mozilla unter Windows , daher gehe ich einfach
> einmal davon aus, dass du auch unter Windows versucht hast das
> nachzuvollziehen. Es ist "leider" nur unter Linux nachvollziehbar wie
> inzwischen klar wurde.

Ja, habs leider erst gesehen, als das Posting schon abgeschickt war :)

Gruß
Michael

Karsten Lentzsch

unread,
Feb 7, 2006, 6:48:15 AM2/7/06
to
Wanja Gayk schrieb:

> [...]

> So wie ich das sehe, führt der SwingWorker nur eine einzelne Arbeit
> außerhalb des EDT aus (die construct()-methode), bietet in ihr einen
> return-Wert und die Möglichkeit nach Abarbeitung der construct()-Methode
> in der finished()-Methode etwas im EDT auszuführen. Richtig?

Ja, das ist sein Schwerpunkt.

> Die JobQueue ist anders.
> Die JobQueue ist nichts anderes, als eine Klasse, die Runnables
> außerhalb des EDT in FIFO-Reihenfolge ausführt, aber nicht nur ein
> einzelnes, sondern du kannst ihr davon so viele davon geben, wie du
> magst. Du kannst mehrere lange Jobs, in schneller Reihenfolge in die
> Queue pumpen, die Queue arbeitet sie dann schön der Reihe nach ab, und
> das, während du du neue hinein jagst.

Interessant.

Der SwingWorker kann synchronisieren auf
eines anderes SwingWorkers Rechenergebnis.
Dadurch kann man Dinge verketten, wenn man will.
Aber das ist nicht sein Schwerpunkt und
nicht offensichtlich.

> [...]

> Damit war garantiert, dass, egal wie oft und mit welcher Geschwindigkeit
> ich das Event auslöse und egal wie lange der einzelne Job dauerte, alles
> immer fein hintereinander ausgeführt wurde, und der EDT trotzdem nicht
> geblockt war. Das Letzte Ergebnis war also auch immer dasd Ergebnis, was
> zuletzt angefordert wurde.

Ich bin gerade in der JGoodies Binding-Mailing-Liste
nach Wegen zu Hintergrundausführungen der Präsentationslogik
gefragt worden. Im Grunde habe ich auch gesagt, dass
eine einfache Lösung die Input-Events sequentiell abarbeitet
(im Hintergrund) und alle anderen Events weiter bearbeitet.
Mein Vorschlag war, zur Sequentialisierung Input-Events
immer dann zu blocken, wenn eins bearbeitet wird,
etwa mittels halbtransparentem GlassPane. Wie in den
Hintergrund geschoben wird, ist dann egal: Spin, Foxtrot,
SwingWorker.

Sehe ich das richtig, das Deine Lösung und mein Vorschlag
ähnliches tun?; oder dieselbe Aufgabe angehen?

-Karsten

Wanja Gayk

unread,
Feb 7, 2006, 9:15:34 AM2/7/06
to
kar...@jgoodies.com said...

> > [...]
> > Damit war garantiert, dass, egal wie oft und mit welcher Geschwindigkeit
> > ich das Event auslöse und egal wie lange der einzelne Job dauerte, alles
> > immer fein hintereinander ausgeführt wurde, und der EDT trotzdem nicht
> > geblockt war. Das Letzte Ergebnis war also auch immer dasd Ergebnis, was
> > zuletzt angefordert wurde.
>
> Ich bin gerade in der JGoodies Binding-Mailing-Liste
> nach Wegen zu Hintergrundausführungen der Präsentationslogik
> gefragt worden. Im Grunde habe ich auch gesagt, dass
> eine einfache Lösung die Input-Events sequentiell abarbeitet
> (im Hintergrund) und alle anderen Events weiter bearbeitet.
> Mein Vorschlag war, zur Sequentialisierung Input-Events
> immer dann zu blocken, wenn eins bearbeitet wird,
> etwa mittels halbtransparentem GlassPane. Wie in den
> Hintergrund geschoben wird, ist dann egal: Spin, Foxtrot,
> SwingWorker.
>
> Sehe ich das richtig, das Deine Lösung und mein Vorschlag
> ähnliches tun?; oder dieselbe Aufgabe angehen?

Nunja, zum Teil. Meine Lösung blockt nix, sondern schickt einfach alles
in eine Warteschleife. Das Blocken kann man damit praktisch kombinieren.

In einem Viewer habe ich derzeit einfach durch setEnabled(..) einen
Button an und später wieder angeschaltet, aber das gab damals Probleme
mit dem FocusManager eines Kollegens, der keine deaktivierten
Komponenten ansprang. Die Glasspane scheint da weniger probleme zu
verursachen.

Mit Foxtrott oder Spin habe ich noch nicht gearbeitet, inwiefern das mit
meiner Queue kompatibel ist, vermag ich also nicht zu sagen.

Je nach dem wo ich die Queue hinstelle kann ich natürlich diese
seuentialisierung für eine Avtion oder für ein ganzes Programm
realisieren. In einem Programm habe ich sie in ein Interface gelegt,
böses Antipattern ich weiß, aber dann konnte jede Klasse
durch simples importieren des Interfaces die selbe, gesharete Queue im
ganzen Programm benutzen. Für den Anwendungsfall war das ganz ordentlich
:-).

0 new messages