QTimer

Alles rund um die Programmierung mit Qt
Antworten
Superheftig
Beiträge: 63
Registriert: 6. September 2008 15:20

QTimer

Beitrag von Superheftig »

Ich habe ein problem mit QTimer und seiner Threadzugehörigkeit. Ich habe folgendes Programm

Code: Alles auswählen

class TestClass : public QThread {

private:

  QNetworkAccessManager* manager;
  QQueue<QString> downloadQueue;

  void run() {
    manager = new QNetworkAccessManager();
    connect(manager, SIGNAL(finished(QNetworkReply*)),
			this, SLOT(downloadFinished(QNetworkReply*)));
   manager->get(QNetworkRequest(QUrl("http://www.testseite.de/index.html")));
    exec();
  }

private slots:
  void downloadFinished(QNetworkReply*) {
    // Starte neuen download falls noch links da sind
    if (downloadQQueue.size() > 0) {
       manager->get(QNetworkRequest(QUrl(downloadQueue.dequeue())));
   }

    // Hier bearbeite ich das reply und suche nach neuen links, die ich dann weiter laden will
     downloadQueue.enqueue("neue links");
  }

}
Mein Problem: Falls die downloadQueue leer ist bleibt das ganze stehen, obwohl der download vieleicht noch garnicht fertig ist. Es könnte ja passieren, dass das aktuelle reply noch links enthällt. Diese werden aber erst nach downloadQQueue.size() > 0 gefunden. Wenn man erst die neuen links suchen würde und dann neue Downloads startet würde es natürlich gehen. Aber während man analysiert, wird ja nichts mehr geladen. Es entstehen also längere wartezeiten, in denen man nichts runterläd.

Ich habe jetzt veruscht durch einen QTimer das ganze wieder zu triggern falls die queue leer war. Da bekomme ich allerdings fehlermeldungen, dass der Timer nicht von einem anderen Thread gestartet und gestoppt werden kann. Den Timer hab ich sowohl in der run Methode als auch in der downloadFinished Methode erstellt. Geht beides nicht.

Wie gehts richtig?
Laufen die Funktionen die durch timeout() ausgelöst werdem in einem eigenständigen Thread?

Oder hat jemand eine andere Idee wie ich den Timer umgehen kann.
CLRS530
Beiträge: 155
Registriert: 8. Oktober 2007 18:00

Beitrag von CLRS530 »

Ich verstehe dein kleines Testprogramm nicht so ganz. Aber ich glaube ich habe das verstanden, was du machen willst, also poste ich hier mal meinen Ansatz... :)

Du möchtest ein Programm entwickeln, das in enem Thread Dateien aus dem Internet läd, die ein anderer Thread in die Queue packt, richtig?
Ich würde im Hauptthread die Links ins Queue packen und einen Thread starten, der in der Run Function in einer "Endlosschleife" die Queue abarbeitet, wenn nichts da ist kannst du z.B. in eine weitere Schleife gehen, die auf ein Signal vom Hauptthread wartet oder sich immer wieder ein paar Sekunden schlafen legt und guckt ob neue Daten da sind.
So wird die Schleife dann auch wirklich Endlos.
Wenn eine Datei fertig geladen ist, kannst du von diesem Thread ein Signal an den Hauptthread schicken (wenn du das Ereignis brauchst).

So wüsste ich dann nicht, wir du zu irgendwelchen Problemen kommen könntest oder gar einen Timer bräuchtest. Willst du den Thread beenden und nicht abschießen (wenn er leer ist), kannst du auch ein Signal vom Hauptthread schicken, wenn er sich beenden soll.
Während du in der 2. Schleife schaust, ob neue Daten da sind, kannst du auch überprüfen, ob der Thread sich nicht vielleicht beenden soll und springst dann raus.

Ich hoffe das ist hilfreich...
Superheftig
Beiträge: 63
Registriert: 6. September 2008 15:20

Beitrag von Superheftig »

Mein problem ist, dass ich den lokalen event loop im Thread brauche für QNetworkAccessManager. Darum kann ich keine Endlosschleife machen. Ich könnte natrülich wie du sagst noch einen anderen Thread starten zum analysieren. Dann hätte ich insgesamt 3 Threads für 2 Aufgaben. In einem läuft der EventLoop, der QNetworkAccessManager hat nen eigenen und mein Analyse Thread...für Aufgaben runterladen und analysieren.
Nicht die beste lösung würde natürlich aber gehen
CLRS530
Beiträge: 155
Registriert: 8. Oktober 2007 18:00

Beitrag von CLRS530 »

Ah ok jetzt verstehe ich das. Aber ist doch auch kein Problem es so zu lösen, wie du es jetzt hast.
Ich würde einen weiteren public slot einführen, den du von deiner Linksammlung aufrufst und zwar genau dann, wenn die queue nach dem befüllen nur ein Element enthält (also vorher leer war... ;)).
In diesem slot guckst du jetzt, ob nicht gerade noch ein download im Gange ist (entweder durch deinen manager oder wenn das nicht geht durch eine lokale variable, die du durch downloadfinished ja immer korrekt setzten kannst). Wenn keiner mehr läuft startest du einen neuen und ansonsten ist ja alles klar und du kannst ihn ohne was zu machen verlassen.

Ich hoffe hier habe ich keine Problemstellung unterschlagen ;)

EDIT1:
Ist natürlich quatsch ein public slot daraus zu machen, eine normale funtion reicht völlig aus...
Superheftig
Beiträge: 63
Registriert: 6. September 2008 15:20

Beitrag von Superheftig »

Danke!

Hab das ganze jetzt gelöst auch ohne timer :)
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

ist wohl obsolete... aber doch noch die Anmerkung: braucht's da ueberhaupt einen Thread? ich habe keine Erfahrung mit dem Manager, aber "This function is used to post a request" bei " get()" bedeutet doch, dass dieser Aufruf nicht-blockierend ist.. Also wuerdest du da gar kein "QThread" brauchen, sondern lediglich ein ganz normales "QObject" zum Verarbeiten der Slots..
Superheftig
Beiträge: 63
Registriert: 6. September 2008 15:20

Beitrag von Superheftig »

Das ganze ist für mich ein wenig verwirrend. In welchem Thread läuft denn der slot downloadFinished wenn ich nicht von QThread erbe und wo läuft er wenn ich von QThread erbe.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

im "normalen" Hauptthread der Applikation... genau gleich wie ein Mausklick und aehnliches..
Antworten