Forum: PC-Programmierung Java: Wie feststellen ob Task abgearbeitet wurde


von Holger (Gast)


Lesenswert?

Hallo,

ich stehe mal wieder auf dem Schlauch:

Also in meinem Hauptprogramm kommen folgende Zeilen vor:
1
Runnable task1 = new ps90Suchen();
2
SwingUtilities.invokeLater(task1);

Jetzt möchte ich irgendwie eine Rückmeldung, wenn task1 durchgelaufen 
ist. Ich habe es schon mit variablen versucht, aber das klappt nicht. 
invokeAndWait ebenfalls nicht...

Wie kann ich das Problem lösen?

Holger

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Was willst du den genau tun? Dein Task ist "fertig" wenn von ps90Suchen 
die run Methode durchlaufen wurde, irgendwie hört sich das aber nicht so 
an als ob du das im GUI-Thread machen wollen würdest, für 
Hintergrundarbeiten die bei Beendigung die GUI aktualisieren sollen gibt 
es die SwingWorker Klasse und dort dann die done() Methode.

von Ahnungsloser (Gast)


Lesenswert?

Hallo,

also ich arbeite mit einem COM-Port und rxtccmm. ps9suchen sucht die 
COM-Ports nach dem Gerät durch. Das soll nebenbei laufen. ps90suchen 
greift aber auch auf die gui zu. Z.B. PS90 an COM1 gefunden in einem 
jtetxfield.

rxtxcomm und Swing ist ein ziemlicher Krampf aber ich habe es nun für 
mich perfekt hinbekommen.

Nun möchte ich, nachdem pc90suchen durch ist, ein zweites Gerät suchen. 
Und der Suchvorgang soll auch "nebenbei" laufen, aber erst, wenn ps90 
abgearbeitet ist.


Holger

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Naja, zum Krampf wird es halt wenn man es "irgendwie" macht ;-)
Leider schwirren auch einige mäßig gute Beispiel im Netz herum.

Ahnungsloser schrieb:
> Das soll nebenbei laufen
Dann ist invokeLater der völlig falsche Weg, das führt nicht dazu das 
es nebenbei läuft, sondern das du sämliche UI blockierst bis dein Task 
abgearbeitet wurde!


Mach dir für dein suchen zwei SwingWorker, pc90 und ps90,
doInBackground() enthält dabei die Hintergrundarbeit, über  publish 
kannst du Nachrichten an die GUI geben, das Ergbnis ist dein Returnwert.

Diese Nachrichten verarbeitest du in der process() methode verarbeiten, 
das Ergebnis der Hintergrundarbeit in done() mittesl der get() methode 
abfragen.

Dein zweiter Worker benötigt nun eine referenz auf den ersten, und fragt 
in seiner doInBackground() methode das isDone() Flag ab, und legt sich 
bei negativem Ergebnis erst mal schlafen... alternativ startet der erste 
Worker den zweiten solabd er fertig ist.

Das alles ließe sich allerdings an einem Konkretem Codebeispiel sehr 
viel besser erläutern.

von Ahnungsloser Holger (Gast)


Lesenswert?

Läubi .. schrieb:
> Dann ist invokeLater der völlig falsche Weg, das führt nicht dazu das
> es nebenbei läuft, sondern das du sämliche UI blockierst bis dein Task
> abgearbeitet wurde!

Moin,

also: GUI wird aufgebaut. Es erscheint: Gerät wird gesucht ...

Dann wird ein Gerät gesucht. Während dieser Zeit ist sowieso nichts mit 
Bedienung der GUI. Während des Suchvorganges werden die 
Schnittsellenbezeichnungen angezeigt. Wenn das Gerät gefunden wurde, 
dann wird die Schnittstelle belegt und dies wird angezeigt. Es läuft in 
vielen Programmen so. Wenn das Gerät aus welchen Gründen nicht gefunden 
wird, dann wird z.B. eine Combobox zur Auswahl der Schnittstelle 
freigegeben.

Aber nun habe ich zum ersten Mal zwei Geräte ...


Holger

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Das mag ja alles sein das es "erstmal" so geht, aber du tust das

a) an der falschen Stelle
b) nicht wie gedacht im Hintergrund

Aber da dich das scheinbar eh nicht stört:

SwingUtilities.invokeLater(task1);
SwingUtilities.invokeLater(task2);

Führt Task2 dann aus wenn Task1 abgeschlossen ist (oder etwas später). 
Aber wie gesagt: schlechtes Design und früher oder später kommt man 
damit in die Bedrulie....

Ahnungsloser Holger schrieb:
> Während dieser Zeit ist sowieso nichts
> mit Bedienung der GUI
Auch das Neuzeichen geht nicht, ggf. blockierst du sogar das Beenden des 
Programms... in kleinem Rahmen mag das gehen, wozu dann aber explizit 
zwei Tasks wenn eh beide nacheinander ablaufen sollen?

von Ahnungsloser Holger (Gast)


Lesenswert?

Moin,

nun lass es mal egals sein was nun richtig oder falsch ist und ob es 
funktioniert oder nicht oder sonst was.

Die Frage ist ja, wie bekomme ich folgendes hin, wobei task1 beendet 
sein muss bevor task2 starten darf:
1
Runnable task1 = new ps90Suchen();
2
SwingUtilities.invokeLater(task1);


1
Runnable task2 = new ps91Suchen();
2
SwingUtilities.invokeLater(task2);



Holger

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Schreib ich doch oben, das macht genau das, erst wird Task1 
abgearbeitet, dann Task2.
Wie ich oben schon schrieb startest du damit keinen Hintergrundthread, 
sondern reihst deine Aufgabe nur in die "Abarbeitungsqueue" des 
GUI-Threads ein, der all diese Aufgaben nacheinander abarbeitet (deshalb 
kann es sein, dass nach task1 noch andere Aufgaben anstehen die erst 
ausgeführt werden, es wird aber auf jedenfall erst Task2 abgearbeitet 
nachdem Task1 abgeschlossen ist).

Falls das "nicht so funktioniert" wie du dir das denkst müsste man mehr 
Code sehen. Wenn da z.B. Callbacks im Spiel sind müsste ggf. Task1 den 
Task2 als Konstruktorparameter kriegen und "am Ende" starten.

von Ahnungsloser Holger (Gast)


Lesenswert?

Läubi .. schrieb:
> Dein zweiter Worker benötigt nun eine referenz auf den ersten, und fragt
> in seiner doInBackground() methode das isDone() Flag ab, und legt sich
> bei negativem Ergebnis erst mal schlafen... alternativ startet der erste
> Worker den zweiten solabd er fertig ist.

Moin,

so, habe jetzt mal auf SwingWorker umgestellt;-) Danke!


Nun habe ich noch eine Frage: Wie mache ich das mit der Referenz?



Gruß
Ahnungsloser Holger

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Entweder über den Konstruktor oder eine setter-Methode was dir lieber 
ist und besser erscheint.

von Ahnungsloser Holger (Gast)


Lesenswert?

Moin!

Kannst Du mir das mal als Beispiel mit zwei SwingWorker darstellen?


Gruß
Holger

von Ahnungsloser Holger (Gast)


Lesenswert?

zu schnell.

Momentan warte ich so ... aber das ist ja wohl nicht ganz korrekt ;-)
1
while(worker.isDone()==false)
2
{
3
     System.out.print(".");
4
     sleepThread(100);
5
}


Ahnungsloser

von Bernd (Gast)


Lesenswert?

Ganz professionell kann man das über den Executor Service machen. Da 
kann man sich benachrichtigen lassen wenn der Task abgearbeitet wurde:
http://openbook.galileocomputing.de/javainsel9/javainsel_14_004.htm#t2t34

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Datentypen musst du ggf. anpassen...
1
 private static final class SwingWorker1 extends SwingWorker<String, String> {
2
        private final SwingWorker<?, ?> otherWorker;
3
4
        public SwingWorker1(SwingWorker<?, ?> otherWorker) {
5
            this.otherWorker = otherWorker;
6
        }
7
8
        @Override
9
        protected String doInBackground() throws Exception {
10
            return "Fertig 1";
11
        }
12
13
        @Override
14
        protected void done() {
15
            otherWorker.execute();
16
            //Tu was sonst so anliegt...
17
        }
18
    }
19
20
    private static final class SwingWorker2 extends SwingWorker<String, String> {
21
        @Override
22
        protected String doInBackground() throws Exception {
23
            return "Fertig 2";
24
        }
25
    }
26
27
    public static void main(String[] args) {
28
        SwingWorker2 sw2 = new SwingWorker2();
29
        SwingWorker1 sw1 = new SwingWorker1(sw2);
30
        sw1.execute();
31
    }

Bernd schrieb:
> Da kann man sich benachrichtigen lassen wenn der
> Task abgearbeitet wurde
Referenz? Man kann dort auch mit Futures arbeiten, was aber keine 
Benachrichtigung enthält... ansonsten ist ein SwingWorker (auch) ein 
Future...

von Ahnungsloser Holger (Gast)


Lesenswert?

Hallo,

danke. Ich glaube ich habe es verstanden!



Ahnungsloser Holger

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.