I
invokeLater
Gast
Servus Forum,
ich arbeite gerade an einer Aufgabenstellung, die darum geht, einen simplen Download Client zu erstellen.
Großteile des Codes sind schon vorgegeben, die Aufgabe besteht darin diesen multithreadbar zu machen, sodass mehrere downloads auf einmal laufen können.
Kurze Beschreibung wie das Ganze aufgebaut ist :
Es gibt das Main-Frame. In diesem wählt man den Pfad der zu downloadenen Datei aus.
Beim Klicken auf "Download" wird dann ein "SaveTo"- Dialog geöffnet, also ein Dialog in dem man den Pfad zum Speichern der Datei auswählt, angelegt.
Dann wird eine Insantz der "DownloadFrameThreaded" Klasse aufgerufen. Das ist im Prinzip ein Frame, das einfach nur eine ProgressBar entählt und einen Button zum Abbrechen des Downloads.
Im Konstruktor von DownloadFrameThreaded erzeuge ich einen DownloadThread. Diesem übergebe ich eine Referenz auf this, damit er Zugriff auf die Methoden zum updaten der ProgressBar von DownloadFrameThreaded hat.
DownloadThread erbt von Thread und überschreibt run(). In run geschieht der gesamte Downloadprozess mit regelmäßigem updaten ( alle 250 ms ) der ProgressBar von DownloadFrameThreaded.
Das funktioniert alles auch wunderbar so, ich kann mehrere Files gleichzeitig downloaden, die ProgressBars werden upgedatet, etc.
Jetzt werden 2 weitere Sachen verlangt, die mir Probleme bereiten :
a ) Wenn der Benutzer in dem DownloadedFrameThreaded auf den Cancel-Button drückt, soll der DownloadThread "gegenfalls" interrupted werden.
Momentan hat das Drücken auf den Cancel-Button eigentlich schon den gewünschten Effekt. Die run()-Methode in DownloadThread hat eine while ( !downloadFrame.isCancelled() ) Schleife. Beim Drücken auf "Cancel" wird isCancelled in DownloadFrameThreaded auf true gesetzt und somit terminiert die Schleife sobald wieder runtime an den Thread gegeben wird und er diese Variable überprüft.
Natürlich wird vorher noch schön aufgeräumt.
So, jetzt verstehe ich nicht, wieso ich noch per interrupt den Thread terminieren soll? ( Na gut, die Aufgabenstellung behauptet das wäre effizienter, da der Rump von run() nicht noch mal ausgeführt wird. Aber ob ein interupt-call schneller ist, naja ... )
1. wirft das eine Exception mit der ich nichts anzufangen weiß. Sie einfach nur zu fangen und nichts damit zu machen fühlt sich falsch an.
2. steht in der Aufgabenstellung "gegebenfalls". Das impliziert, dass ich vorher irgendwas überprüfen soll? Aber ich wüsste nicht was ;/
b) Das größere Problem : Swing ist ja bekannterweise nicht Threadsicher. Und ich versuche von einem anderen Thread als dem Swing-Thread aus GUI-Komponenten upzudaten. Momentan funktioniert das wunderbar, aber ist wahrscheinlich UB.
Deshalb verlangt die Aufgabenstellung, dass man die Methoden, die die ProgressBar updaten, beispielsweise, mit SwingUtilities.invokeLater , threadsicher macht.
Allerdings verlangt SwingUtilities.invokeLater als Argument ein Objekt das wohl zumindestens von Runable() erbt. Ich hab mir ein paar Beispielcodes dazu angeschaut, habe allerdings immernoch keinen blassen Schimmer wie ich diese Funktion auf meinen Code anwenden soll.
Beispielsweise
kann ich ja kaum unter Verwendung von SwingUtilities.invokeLater umschreiben. Da mus sich irgendwo anders ansetzen.
Der Thread wird beispielsweise so gestartet, in DownloadFrameThreaded :
irgendwie ja zu erwarten. Probeweise habe ich probiert :
Zwar wird die Datei dann noch downloaded, aber die ProgressBar wird nie updated.
Vielen Dank schon mal fürs Durchlesen und danke im Voraus für Antworten!
Wenn ihr noch zusätzlich mehr Code braucht, dann bitte einfach schreiben, wollte diesen Post hier nicht unnötig groß machen.
Mfg und schönen Abend noch
ich arbeite gerade an einer Aufgabenstellung, die darum geht, einen simplen Download Client zu erstellen.
Großteile des Codes sind schon vorgegeben, die Aufgabe besteht darin diesen multithreadbar zu machen, sodass mehrere downloads auf einmal laufen können.
Kurze Beschreibung wie das Ganze aufgebaut ist :
Es gibt das Main-Frame. In diesem wählt man den Pfad der zu downloadenen Datei aus.
Beim Klicken auf "Download" wird dann ein "SaveTo"- Dialog geöffnet, also ein Dialog in dem man den Pfad zum Speichern der Datei auswählt, angelegt.
Dann wird eine Insantz der "DownloadFrameThreaded" Klasse aufgerufen. Das ist im Prinzip ein Frame, das einfach nur eine ProgressBar entählt und einen Button zum Abbrechen des Downloads.
Im Konstruktor von DownloadFrameThreaded erzeuge ich einen DownloadThread. Diesem übergebe ich eine Referenz auf this, damit er Zugriff auf die Methoden zum updaten der ProgressBar von DownloadFrameThreaded hat.
DownloadThread erbt von Thread und überschreibt run(). In run geschieht der gesamte Downloadprozess mit regelmäßigem updaten ( alle 250 ms ) der ProgressBar von DownloadFrameThreaded.
Das funktioniert alles auch wunderbar so, ich kann mehrere Files gleichzeitig downloaden, die ProgressBars werden upgedatet, etc.
Jetzt werden 2 weitere Sachen verlangt, die mir Probleme bereiten :
a ) Wenn der Benutzer in dem DownloadedFrameThreaded auf den Cancel-Button drückt, soll der DownloadThread "gegenfalls" interrupted werden.
Momentan hat das Drücken auf den Cancel-Button eigentlich schon den gewünschten Effekt. Die run()-Methode in DownloadThread hat eine while ( !downloadFrame.isCancelled() ) Schleife. Beim Drücken auf "Cancel" wird isCancelled in DownloadFrameThreaded auf true gesetzt und somit terminiert die Schleife sobald wieder runtime an den Thread gegeben wird und er diese Variable überprüft.
Natürlich wird vorher noch schön aufgeräumt.
So, jetzt verstehe ich nicht, wieso ich noch per interrupt den Thread terminieren soll? ( Na gut, die Aufgabenstellung behauptet das wäre effizienter, da der Rump von run() nicht noch mal ausgeführt wird. Aber ob ein interupt-call schneller ist, naja ... )
1. wirft das eine Exception mit der ich nichts anzufangen weiß. Sie einfach nur zu fangen und nichts damit zu machen fühlt sich falsch an.
2. steht in der Aufgabenstellung "gegebenfalls". Das impliziert, dass ich vorher irgendwas überprüfen soll? Aber ich wüsste nicht was ;/
b) Das größere Problem : Swing ist ja bekannterweise nicht Threadsicher. Und ich versuche von einem anderen Thread als dem Swing-Thread aus GUI-Komponenten upzudaten. Momentan funktioniert das wunderbar, aber ist wahrscheinlich UB.
Deshalb verlangt die Aufgabenstellung, dass man die Methoden, die die ProgressBar updaten, beispielsweise, mit SwingUtilities.invokeLater , threadsicher macht.
Allerdings verlangt SwingUtilities.invokeLater als Argument ein Objekt das wohl zumindestens von Runable() erbt. Ich hab mir ein paar Beispielcodes dazu angeschaut, habe allerdings immernoch keinen blassen Schimmer wie ich diese Funktion auf meinen Code anwenden soll.
Beispielsweise
Java:
// innerhalbe der while Schleife in DownloadThread.run()
frame.setProgress((int)(totalBytes * 100L / size)); // Hier wird die Progressbar from frame updated
kann ich ja kaum unter Verwendung von SwingUtilities.invokeLater umschreiben. Da mus sich irgendwo anders ansetzen.
Der Thread wird beispielsweise so gestartet, in DownloadFrameThreaded :
Java:
downloadThread.start();
irgendwie ja zu erwarten. Probeweise habe ich probiert :
Java:
SwingUtilities.invokeLater(downloadThread);
Zwar wird die Datei dann noch downloaded, aber die ProgressBar wird nie updated.
Vielen Dank schon mal fürs Durchlesen und danke im Voraus für Antworten!
Wenn ihr noch zusätzlich mehr Code braucht, dann bitte einfach schreiben, wollte diesen Post hier nicht unnötig groß machen.
Mfg und schönen Abend noch